Do not rely on PreviousSpec for storing desired replica count

This commit is contained in:
Frederik Ring 2024-01-27 12:23:09 +01:00
parent f4497177b5
commit 94aa33369f

View File

@ -327,6 +327,11 @@ func (noopWriteCloser) Close() error {
return nil return nil
} }
type handledSwarmService struct {
serviceID string
initialReplicaCount uint64
}
// stopContainersAndServices stops all Docker containers that are marked as to being // stopContainersAndServices stops all Docker containers that are marked as to being
// stopped during the backup and returns a function that can be called to // stopped during the backup and returns a function that can be called to
// restart everything that has been stopped. // restart everything that has been stopped.
@ -362,19 +367,25 @@ func (s *script) stopContainersAndServices() (func() error, error) {
} }
var allServices []swarm.Service var allServices []swarm.Service
var servicesToScaleDown []swarm.Service var servicesToScaleDown []handledSwarmService
if isDockerSwarm { if isDockerSwarm {
allServices, err = s.cli.ServiceList(context.Background(), types.ServiceListOptions{}) allServices, err = s.cli.ServiceList(context.Background(), types.ServiceListOptions{})
if err != nil { if err != nil {
return noop, fmt.Errorf("(*script).stopContainersAndServices: error querying for services: %w", err) return noop, fmt.Errorf("(*script).stopContainersAndServices: error querying for services: %w", err)
} }
servicesToScaleDown, err = s.cli.ServiceList(context.Background(), types.ServiceListOptions{ matchingServices, err := s.cli.ServiceList(context.Background(), types.ServiceListOptions{
Filters: filters.NewArgs(filters.KeyValuePair{ Filters: filters.NewArgs(filters.KeyValuePair{
Key: "label", Key: "label",
Value: filterMatchLabel, Value: filterMatchLabel,
}), }),
Status: true, Status: true,
}) })
for _, s := range matchingServices {
servicesToScaleDown = append(servicesToScaleDown, handledSwarmService{
serviceID: s.ID,
initialReplicaCount: *s.Spec.Mode.Replicated.Replicas,
})
}
if err != nil { if err != nil {
return noop, fmt.Errorf("(*script).stopContainersAndServices: error querying for services to scale down: %w", err) return noop, fmt.Errorf("(*script).stopContainersAndServices: error querying for services to scale down: %w", err)
} }
@ -408,7 +419,15 @@ func (s *script) stopContainersAndServices() (func() error, error) {
var scaledDownServices []swarm.Service var scaledDownServices []swarm.Service
var scaleDownErrors []error var scaleDownErrors []error
if isDockerSwarm { if isDockerSwarm {
for _, service := range servicesToScaleDown { for _, svc := range servicesToScaleDown {
service, _, err := s.cli.ServiceInspectWithRaw(context.Background(), svc.serviceID, types.ServiceInspectOptions{})
if err != nil {
scaleDownErrors = append(
scaleDownErrors,
fmt.Errorf("(*script).stopContainersAndServices: error inspecting service %s: %w", svc.serviceID, err),
)
continue
}
var zero uint64 = 0 var zero uint64 = 0
serviceMode := &service.Spec.Mode serviceMode := &service.Spec.Mode
switch { switch {
@ -422,7 +441,7 @@ func (s *script) stopContainersAndServices() (func() error, error) {
continue continue
} }
_, err := s.cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) _, err = s.cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{})
if err != nil { if err != nil {
scaleDownErrors = append(scaleDownErrors, err) scaleDownErrors = append(scaleDownErrors, err)
} }
@ -502,31 +521,23 @@ func (s *script) stopContainersAndServices() (func() error, error) {
var scaleUpErrors []error var scaleUpErrors []error
if isDockerSwarm { if isDockerSwarm {
for _, service := range servicesToScaleDown { for _, svc := range servicesToScaleDown {
updatedService, _, err := s.cli.ServiceInspectWithRaw(context.Background(), service.ID, types.ServiceInspectOptions{}) service, _, err := s.cli.ServiceInspectWithRaw(context.Background(), svc.serviceID, types.ServiceInspectOptions{})
if err != nil { if err != nil {
scaleUpErrors = append(scaleUpErrors, err) scaleUpErrors = append(scaleUpErrors, err)
continue continue
} }
if updatedService.PreviousSpec == nil { service.Spec.Mode.Replicated.Replicas = &svc.initialReplicaCount
scaleUpErrors = append(
scaleUpErrors,
errors.New("(*script).stopContainersAndServices: service does not have PreviousSpec, cannot scale back up."),
)
continue
}
updatedService.Spec.Mode.Replicated.Replicas = updatedService.PreviousSpec.Mode.Replicated.Replicas
if _, err := s.cli.ServiceUpdate( if _, err := s.cli.ServiceUpdate(
context.Background(), context.Background(),
updatedService.ID, service.ID,
updatedService.Version, updatedService.Spec, service.Version, service.Spec,
types.ServiceUpdateOptions{}, types.ServiceUpdateOptions{},
); err != nil { ); err != nil {
scaleUpErrors = append(scaleUpErrors, err) scaleUpErrors = append(scaleUpErrors, err)
} }
if err := progress.ServiceProgress(context.Background(), s.cli, updatedService.ID, discardWriter); err != nil { if err := progress.ServiceProgress(context.Background(), s.cli, service.ID, discardWriter); err != nil {
scaleUpErrors = append(scaleUpErrors, err) scaleUpErrors = append(scaleUpErrors, err)
} }
} }