github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/cli/command/service/scale.go (about) 1 package service 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "golang.org/x/net/context" 9 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/cli" 12 "github.com/docker/docker/cli/command" 13 "github.com/spf13/cobra" 14 ) 15 16 func newScaleCommand(dockerCli *command.DockerCli) *cobra.Command { 17 return &cobra.Command{ 18 Use: "scale SERVICE=REPLICAS [SERVICE=REPLICAS...]", 19 Short: "Scale one or multiple services", 20 Args: scaleArgs, 21 RunE: func(cmd *cobra.Command, args []string) error { 22 return runScale(dockerCli, args) 23 }, 24 } 25 } 26 27 func scaleArgs(cmd *cobra.Command, args []string) error { 28 if err := cli.RequiresMinArgs(1)(cmd, args); err != nil { 29 return err 30 } 31 for _, arg := range args { 32 if parts := strings.SplitN(arg, "=", 2); len(parts) != 2 { 33 return fmt.Errorf( 34 "Invalid scale specifier '%s'.\nSee '%s --help'.\n\nUsage: %s\n\n%s", 35 arg, 36 cmd.CommandPath(), 37 cmd.UseLine(), 38 cmd.Short, 39 ) 40 } 41 } 42 return nil 43 } 44 45 func runScale(dockerCli *command.DockerCli, args []string) error { 46 var errors []string 47 for _, arg := range args { 48 parts := strings.SplitN(arg, "=", 2) 49 serviceID, scaleStr := parts[0], parts[1] 50 51 // validate input arg scale number 52 scale, err := strconv.ParseUint(scaleStr, 10, 64) 53 if err != nil { 54 errors = append(errors, fmt.Sprintf("%s: invalid replicas value %s: %v", serviceID, scaleStr, err)) 55 continue 56 } 57 58 if err := runServiceScale(dockerCli, serviceID, scale); err != nil { 59 errors = append(errors, fmt.Sprintf("%s: %v", serviceID, err)) 60 } 61 } 62 63 if len(errors) == 0 { 64 return nil 65 } 66 return fmt.Errorf(strings.Join(errors, "\n")) 67 } 68 69 func runServiceScale(dockerCli *command.DockerCli, serviceID string, scale uint64) error { 70 client := dockerCli.Client() 71 ctx := context.Background() 72 73 service, _, err := client.ServiceInspectWithRaw(ctx, serviceID) 74 if err != nil { 75 return err 76 } 77 78 serviceMode := &service.Spec.Mode 79 if serviceMode.Replicated == nil { 80 return fmt.Errorf("scale can only be used with replicated mode") 81 } 82 83 serviceMode.Replicated.Replicas = &scale 84 85 err = client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 86 if err != nil { 87 return err 88 } 89 90 fmt.Fprintf(dockerCli.Out(), "%s scaled to %d\n", serviceID, scale) 91 return nil 92 }