mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
d4392659f7
Modify the service update and create APIs to return optional warning
messages as part of the response. Populate these messages with an
informative reason when digest resolution fails.
This is a small API change, but significantly improves the UX. The user
can now get immediate feedback when they've specified a nonexistent
image or unreachable registry.
Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
(cherry picked from commit 948e60691e
)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/cli"
|
|
"github.com/docker/docker/cli/command"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func newScaleCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "scale SERVICE=REPLICAS [SERVICE=REPLICAS...]",
|
|
Short: "Scale one or multiple replicated services",
|
|
Args: scaleArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return runScale(dockerCli, args)
|
|
},
|
|
}
|
|
}
|
|
|
|
func scaleArgs(cmd *cobra.Command, args []string) error {
|
|
if err := cli.RequiresMinArgs(1)(cmd, args); err != nil {
|
|
return err
|
|
}
|
|
for _, arg := range args {
|
|
if parts := strings.SplitN(arg, "=", 2); len(parts) != 2 {
|
|
return fmt.Errorf(
|
|
"Invalid scale specifier '%s'.\nSee '%s --help'.\n\nUsage: %s\n\n%s",
|
|
arg,
|
|
cmd.CommandPath(),
|
|
cmd.UseLine(),
|
|
cmd.Short,
|
|
)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func runScale(dockerCli *command.DockerCli, args []string) error {
|
|
var errors []string
|
|
for _, arg := range args {
|
|
parts := strings.SplitN(arg, "=", 2)
|
|
serviceID, scaleStr := parts[0], parts[1]
|
|
|
|
// validate input arg scale number
|
|
scale, err := strconv.ParseUint(scaleStr, 10, 64)
|
|
if err != nil {
|
|
errors = append(errors, fmt.Sprintf("%s: invalid replicas value %s: %v", serviceID, scaleStr, err))
|
|
continue
|
|
}
|
|
|
|
if err := runServiceScale(dockerCli, serviceID, scale); err != nil {
|
|
errors = append(errors, fmt.Sprintf("%s: %v", serviceID, err))
|
|
}
|
|
}
|
|
|
|
if len(errors) == 0 {
|
|
return nil
|
|
}
|
|
return fmt.Errorf(strings.Join(errors, "\n"))
|
|
}
|
|
|
|
func runServiceScale(dockerCli *command.DockerCli, serviceID string, scale uint64) error {
|
|
client := dockerCli.Client()
|
|
ctx := context.Background()
|
|
|
|
service, _, err := client.ServiceInspectWithRaw(ctx, serviceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
serviceMode := &service.Spec.Mode
|
|
if serviceMode.Replicated == nil {
|
|
return fmt.Errorf("scale can only be used with replicated mode")
|
|
}
|
|
|
|
serviceMode.Replicated.Replicas = &scale
|
|
|
|
response, err := client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, warning := range response.Warnings {
|
|
fmt.Fprintln(dockerCli.Err(), warning)
|
|
}
|
|
|
|
fmt.Fprintf(dockerCli.Out(), "%s scaled to %d\n", serviceID, scale)
|
|
return nil
|
|
}
|