Files
docker-cli/cli/command/stack/swarm/deploy.go
Sebastiaan van Stijn 2066dbcfe8 cli/command/stack/swarm: inline validateResolveImageFlag
It was only used in a single place, and possibly incorrect. Let's inline
it to put the logic where it's used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-29 14:39:06 +02:00

83 lines
2.9 KiB
Go

package swarm
import (
"context"
"fmt"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/stack/options"
"github.com/docker/cli/cli/compose/convert"
composetypes "github.com/docker/cli/cli/compose/types"
"github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/api/types/versions"
"github.com/pkg/errors"
"github.com/spf13/pflag"
)
// Resolve image constants
const (
defaultNetworkDriver = "overlay"
ResolveImageAlways = "always"
ResolveImageChanged = "changed"
ResolveImageNever = "never"
)
// RunDeploy is the swarm implementation of docker stack deploy
//
// Deprecated: this function was for internal use and will be removed in the next release.
func RunDeploy(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opts *options.Deploy, cfg *composetypes.Config) error {
switch opts.ResolveImage {
case ResolveImageAlways, ResolveImageChanged, ResolveImageNever:
// valid options.
default:
return errors.Errorf("Invalid option %s for flag --resolve-image", opts.ResolveImage)
}
// client side image resolution should not be done when the supported
// server version is older than 1.30
if versions.LessThan(dockerCLI.Client().ClientVersion(), "1.30") {
// TODO(thaJeztah): should this error if "opts.ResolveImage" is already other (unsupported) values?
opts.ResolveImage = ResolveImageNever
}
if opts.Detach && !flags.Changed("detach") {
_, _ = fmt.Fprintln(dockerCLI.Err(), "Since --detach=false was not specified, tasks will be created in the background.\n"+
"In a future release, --detach=false will become the default.")
}
return deployCompose(ctx, dockerCLI, opts, cfg)
}
// checkDaemonIsSwarmManager does an Info API call to verify that the daemon is
// a swarm manager. This is necessary because we must create networks before we
// create services, but the API call for creating a network does not return a
// proper status code when it can't create a network in the "global" scope.
func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error {
info, err := dockerCli.Client().Info(ctx)
if err != nil {
return err
}
if !info.Swarm.ControlAvailable {
return errors.New("this node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again")
}
return nil
}
// pruneServices removes services that are no longer referenced in the source
func pruneServices(ctx context.Context, dockerCLI command.Cli, namespace convert.Namespace, services map[string]struct{}) {
apiClient := dockerCLI.Client()
oldServices, err := getStackServices(ctx, apiClient, namespace.Name())
if err != nil {
_, _ = fmt.Fprintln(dockerCLI.Err(), "Failed to list services:", err)
}
toRemove := make([]swarm.Service, 0, len(oldServices))
for _, service := range oldServices {
if _, exists := services[namespace.Descope(service.Spec.Name)]; !exists {
toRemove = append(toRemove, service)
}
}
removeServices(ctx, dockerCLI, toRemove)
}