Merge pull request #6398 from thaJeztah/rm_deprecated_stack

cli/command/stack: remove some deprecated functions
This commit is contained in:
Rob Murray 2025-08-29 17:23:29 +01:00 committed by GitHub
commit 81ea282e00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 105 additions and 159 deletions

View File

@ -4,6 +4,10 @@ import (
"fmt"
"strings"
"unicode"
"github.com/docker/cli/cli/compose/convert"
"github.com/docker/cli/opts"
"github.com/moby/moby/api/types/filters"
)
// validateStackName checks if the provided string is a valid stack name (namespace).
@ -29,3 +33,9 @@ func validateStackNames(namespaces []string) error {
func quotesOrWhitespace(r rune) bool {
return unicode.IsSpace(r) || r == '"' || r == '\''
}
func getStackFilterFromOpt(namespace string, opt opts.FilterOpt) filters.Args {
filter := opt.Value()
filter.Add("label", convert.LabelNamespace+"="+namespace)
return filter
}

View File

@ -9,16 +9,18 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/command/stack/formatter"
"github.com/docker/cli/cli/command/stack/options"
"github.com/docker/cli/cli/command/stack/swarm"
flagsHelper "github.com/docker/cli/cli/flags"
"github.com/fvbommel/sortorder"
"github.com/spf13/cobra"
)
type listOptions = options.List
// listOptions holds docker stack ls options
type listOptions struct {
format string
}
func newListCommand(dockerCli command.Cli) *cobra.Command {
func newListCommand(dockerCLI command.Cli) *cobra.Command {
opts := listOptions{}
cmd := &cobra.Command{
@ -27,23 +29,16 @@ func newListCommand(dockerCli command.Cli) *cobra.Command {
Short: "List stacks",
Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runList(cmd.Context(), dockerCli, opts)
return runList(cmd.Context(), dockerCLI, opts)
},
ValidArgsFunction: completion.NoComplete,
}
flags := cmd.Flags()
flags.StringVar(&opts.Format, "format", "", flagsHelper.FormatHelp)
flags.StringVar(&opts.format, "format", "", flagsHelper.FormatHelp)
return cmd
}
// RunList performs a stack list against the specified swarm cluster
//
// Deprecated: this function was for internal use and will be removed in the next release.
func RunList(ctx context.Context, dockerCLI command.Cli, opts options.List) error {
return runList(ctx, dockerCLI, opts)
}
// runList performs a stack list against the specified swarm cluster
func runList(ctx context.Context, dockerCLI command.Cli, opts listOptions) error {
stacks, err := swarm.GetStacks(ctx, dockerCLI.Client())
@ -54,7 +49,7 @@ func runList(ctx context.Context, dockerCLI command.Cli, opts listOptions) error
}
func format(out io.Writer, opts listOptions, stacks []formatter.Stack) error {
fmt := formatter.Format(opts.Format)
fmt := formatter.Format(opts.format)
if fmt == "" || fmt == formatter.TableFormatKey {
fmt = formatter.SwarmStackTableFormat
}

View File

@ -1,7 +1,5 @@
package options
import "github.com/docker/cli/opts"
// Deploy holds docker stack deploy options
//
// Deprecated: this type was for internal use and will be removed in the next release.
@ -23,26 +21,6 @@ type Config struct {
SkipInterpolation bool
}
// List holds docker stack ls options
//
// Deprecated: this type was for internal use and will be removed in the next release.
type List struct {
Format string
AllNamespaces bool
}
// PS holds docker stack ps options
//
// Deprecated: this type was for internal use and will be removed in the next release.
type PS struct {
Filter opts.FilterOpt
NoTrunc bool
Namespace string
NoResolve bool
Quiet bool
Format string
}
// Remove holds docker stack remove options
//
// Deprecated: this type was for internal use and will be removed in the next release.
@ -50,13 +28,3 @@ type Remove struct {
Namespaces []string
Detach bool
}
// Services holds docker stack services options
//
// Deprecated: this type was for internal use and will be removed in the next release.
type Services struct {
Quiet bool
Format string
Filter opts.FilterOpt
Namespace string
}

View File

@ -1,38 +1,73 @@
package stack
import (
"context"
"fmt"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/stack/options"
"github.com/docker/cli/cli/command/stack/swarm"
"github.com/docker/cli/cli/command/idresolver"
"github.com/docker/cli/cli/command/task"
flagsHelper "github.com/docker/cli/cli/flags"
cliopts "github.com/docker/cli/opts"
"github.com/moby/moby/client"
"github.com/spf13/cobra"
)
func newPsCommand(dockerCli command.Cli) *cobra.Command {
opts := options.PS{Filter: cliopts.NewFilterOpt()}
// psOptions holds docker stack ps options
type psOptions struct {
filter cliopts.FilterOpt
noTrunc bool
namespace string
noResolve bool
quiet bool
format string
}
func newPsCommand(dockerCLI command.Cli) *cobra.Command {
opts := psOptions{filter: cliopts.NewFilterOpt()}
cmd := &cobra.Command{
Use: "ps [OPTIONS] STACK",
Short: "List the tasks in the stack",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.Namespace = args[0]
if err := validateStackName(opts.Namespace); err != nil {
opts.namespace = args[0]
if err := validateStackName(opts.namespace); err != nil {
return err
}
return swarm.RunPS(cmd.Context(), dockerCli, opts)
return runPS(cmd.Context(), dockerCLI, opts)
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return completeNames(dockerCli)(cmd, args, toComplete)
return completeNames(dockerCLI)(cmd, args, toComplete)
},
}
flags := cmd.Flags()
flags.BoolVar(&opts.NoTrunc, "no-trunc", false, "Do not truncate output")
flags.BoolVar(&opts.NoResolve, "no-resolve", false, "Do not map IDs to Names")
flags.VarP(&opts.Filter, "filter", "f", "Filter output based on conditions provided")
flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display task IDs")
flags.StringVar(&opts.Format, "format", "", flagsHelper.FormatHelp)
flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate output")
flags.BoolVar(&opts.noResolve, "no-resolve", false, "Do not map IDs to Names")
flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display task IDs")
flags.StringVar(&opts.format, "format", "", flagsHelper.FormatHelp)
return cmd
}
// runPS is the swarm implementation of docker stack ps
func runPS(ctx context.Context, dockerCLI command.Cli, opts psOptions) error {
apiClient := dockerCLI.Client()
tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{
Filters: getStackFilterFromOpt(opts.namespace, opts.filter),
})
if err != nil {
return err
}
if len(tasks) == 0 {
return fmt.Errorf("nothing found in stack: %s", opts.namespace)
}
if opts.format == "" {
opts.format = task.DefaultFormat(dockerCLI.ConfigFile(), opts.quiet)
}
return task.Print(ctx, dockerCLI, tasks, idresolver.New(apiClient, opts.noResolve), !opts.noTrunc, opts.quiet, opts.format)
}

View File

@ -7,30 +7,33 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/cli/command/service"
"github.com/docker/cli/cli/command/stack/formatter"
"github.com/docker/cli/cli/command/stack/options"
"github.com/docker/cli/cli/command/stack/swarm"
flagsHelper "github.com/docker/cli/cli/flags"
cliopts "github.com/docker/cli/opts"
"github.com/fvbommel/sortorder"
swarmtypes "github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/api/types/swarm"
"github.com/spf13/cobra"
)
// servicesOptions holds docker stack services options
type servicesOptions = options.Services
// serviceListOptions holds docker stack services options
type serviceListOptions = struct {
quiet bool
format string
filter cliopts.FilterOpt
namespace string
}
func newServicesCommand(dockerCLI command.Cli) *cobra.Command {
opts := servicesOptions{Filter: cliopts.NewFilterOpt()}
opts := serviceListOptions{filter: cliopts.NewFilterOpt()}
cmd := &cobra.Command{
Use: "services [OPTIONS] STACK",
Short: "List the services in the stack",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.Namespace = args[0]
if err := validateStackName(opts.Namespace); err != nil {
opts.namespace = args[0]
if err := validateStackName(opts.namespace); err != nil {
return err
}
return runServices(cmd.Context(), dockerCLI, opts)
@ -40,41 +43,34 @@ func newServicesCommand(dockerCLI command.Cli) *cobra.Command {
},
}
flags := cmd.Flags()
flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
flags.StringVar(&opts.Format, "format", "", flagsHelper.FormatHelp)
flags.VarP(&opts.Filter, "filter", "f", "Filter output based on conditions provided")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display IDs")
flags.StringVar(&opts.format, "format", "", flagsHelper.FormatHelp)
flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")
return cmd
}
// RunServices performs a stack services against the specified swarm cluster
//
// Deprecated: this function was for internal use and will be removed in the next release.
func RunServices(ctx context.Context, dockerCLI command.Cli, opts options.Services) error {
return runServices(ctx, dockerCLI, opts)
}
// runServices performs a stack services against the specified swarm cluster
func runServices(ctx context.Context, dockerCLI command.Cli, opts servicesOptions) error {
services, err := swarm.GetServices(ctx, dockerCLI, opts)
func runServices(ctx context.Context, dockerCLI command.Cli, opts serviceListOptions) error {
services, err := getServices(ctx, dockerCLI.Client(), opts)
if err != nil {
return err
}
return formatWrite(dockerCLI, services, opts)
}
func formatWrite(dockerCLI command.Cli, services []swarmtypes.Service, opts servicesOptions) error {
func formatWrite(dockerCLI command.Cli, services []swarm.Service, opts serviceListOptions) error {
// if no services in the stack, print message and exit 0
if len(services) == 0 {
_, _ = fmt.Fprintln(dockerCLI.Err(), "Nothing found in stack:", opts.Namespace)
_, _ = fmt.Fprintln(dockerCLI.Err(), "Nothing found in stack:", opts.namespace)
return nil
}
sort.Slice(services, func(i, j int) bool {
return sortorder.NaturalLess(services[i].Spec.Name, services[j].Spec.Name)
})
f := opts.Format
f := opts.format
if len(f) == 0 {
if len(dockerCLI.ConfigFile().ServicesFormat) > 0 && !opts.Quiet {
if len(dockerCLI.ConfigFile().ServicesFormat) > 0 && !opts.quiet {
f = dockerCLI.ConfigFile().ServicesFormat
} else {
f = formatter.TableFormatKey
@ -83,7 +79,7 @@ func formatWrite(dockerCLI command.Cli, services []swarmtypes.Service, opts serv
servicesCtx := formatter.Context{
Output: dockerCLI.Out(),
Format: service.NewListFormat(f, opts.Quiet),
Format: service.NewListFormat(f, opts.quiet),
}
return service.ListFormatWrite(servicesCtx, services)
}

View File

@ -1,31 +1,22 @@
package swarm
package stack
import (
"context"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/service"
"github.com/docker/cli/cli/command/stack/options"
"github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/client"
)
// GetServices is the swarm implementation of listing stack services
//
// Deprecated: this function was for internal use and will be removed in the next release.
func GetServices(ctx context.Context, dockerCLI command.Cli, opts options.Services) ([]swarm.Service, error) {
var (
err error
apiClient = dockerCLI.Client()
)
// getServices is the swarm implementation of listing stack services
func getServices(ctx context.Context, apiClient client.APIClient, opts serviceListOptions) ([]swarm.Service, error) {
listOpts := client.ServiceListOptions{
Filters: getStackFilterFromOpt(opts.Namespace, opts.Filter),
Filters: getStackFilterFromOpt(opts.namespace, opts.filter),
// When not running "quiet", also get service status (number of running
// and desired tasks). Note that this is only supported on API v1.41 and
// up; older API versions ignore this option, and we will have to collect
// the information manually below.
Status: !opts.Quiet,
Status: !opts.quiet,
}
services, err := apiClient.ServiceList(ctx, listOpts)

View File

@ -4,7 +4,6 @@ import (
"context"
"github.com/docker/cli/cli/compose/convert"
"github.com/docker/cli/opts"
"github.com/moby/moby/api/types/filters"
"github.com/moby/moby/api/types/network"
"github.com/moby/moby/api/types/swarm"
@ -17,12 +16,6 @@ func getStackFilter(namespace string) filters.Args {
return filter
}
func getStackFilterFromOpt(namespace string, opt opts.FilterOpt) filters.Args {
filter := opt.Value()
filter.Add("label", convert.LabelNamespace+"="+namespace)
return filter
}
func getAllStacksFilter() filters.Args {
filter := filters.NewArgs()
filter.Add("label", convert.LabelNamespace)

View File

@ -26,12 +26,17 @@ const (
//
// 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 {
if err := validateResolveImageFlag(opts); err != nil {
return err
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
}
@ -43,16 +48,6 @@ func RunDeploy(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet,
return deployCompose(ctx, dockerCLI, opts, cfg)
}
// validateResolveImageFlag validates the opts.resolveImage command line option
func validateResolveImageFlag(opts *options.Deploy) error {
switch opts.ResolveImage {
case ResolveImageAlways, ResolveImageChanged, ResolveImageNever:
return nil
default:
return errors.Errorf("Invalid option %s for flag --resolve-image", opts.ResolveImage)
}
}
// 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

View File

@ -265,14 +265,13 @@ func deployServices(ctx context.Context, dockerCLI command.Cli, services map[str
} else {
_, _ = fmt.Fprintln(out, "Creating service", name)
createOpts := client.ServiceCreateOptions{EncodedRegistryAuth: encodedAuth}
// query registry if flag disabling it was not set
if resolveImage == ResolveImageAlways || resolveImage == ResolveImageChanged {
createOpts.QueryRegistry = true
}
queryRegistry := resolveImage == ResolveImageAlways || resolveImage == ResolveImageChanged
response, err := apiClient.ServiceCreate(ctx, serviceSpec, createOpts)
response, err := apiClient.ServiceCreate(ctx, serviceSpec, client.ServiceCreateOptions{
EncodedRegistryAuth: encodedAuth,
QueryRegistry: queryRegistry,
})
if err != nil {
return nil, fmt.Errorf("failed to create service %s: %w", name, err)
}

View File

@ -1,36 +0,0 @@
package swarm
import (
"context"
"fmt"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/idresolver"
"github.com/docker/cli/cli/command/stack/options"
"github.com/docker/cli/cli/command/task"
"github.com/moby/moby/client"
)
// RunPS is the swarm implementation of docker stack ps
//
// Deprecated: this function was for internal use and will be removed in the next release.
func RunPS(ctx context.Context, dockerCLI command.Cli, opts options.PS) error {
filter := getStackFilterFromOpt(opts.Namespace, opts.Filter)
apiClient := dockerCLI.Client()
tasks, err := apiClient.TaskList(ctx, client.TaskListOptions{Filters: filter})
if err != nil {
return err
}
if len(tasks) == 0 {
return fmt.Errorf("nothing found in stack: %s", opts.Namespace)
}
format := opts.Format
if len(format) == 0 {
format = task.DefaultFormat(dockerCLI.ConfigFile(), opts.Quiet)
}
return task.Print(ctx, dockerCLI, tasks, idresolver.New(apiClient, opts.NoResolve), !opts.NoTrunc, opts.Quiet, format)
}