swarmd/cmd/swarmctl/service/flagparser/flags.go
package flagparser
import (
"fmt"
"strings"
"github.com/moby/swarmkit/swarmd/cmd/swarmctl/common"
"github.com/moby/swarmkit/v2/api"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
// AddServiceFlags add all supported service flags to the flagset.
func AddServiceFlags(flags *pflag.FlagSet) {
flags.String("name", "", "service name")
flags.StringSlice("label", nil, "service label (key=value)")
flags.Uint64("replicas", 1, "number of replicas for the service (only works in replicated service mode)")
flags.Uint64("replicas-max-per-node", 0, "maximum number of replicas for per node (only works in replicated service mode) (default 0 = unlimited)")
flags.String("image", "", "container image")
flags.String("hostname", "", "container hostname")
flags.StringSlice("command", nil, "override entrypoint")
flags.StringSlice("args", nil, "container args")
flags.StringSlice("env", nil, "container env")
flags.Bool("tty", false, "open a tty on standard streams")
flags.Bool("open-stdin", false, "open standard input")
flags.StringSlice("ports", nil, "ports")
flags.String("network", "", "network name")
flags.String("memory-reservation", "", "amount of reserved memory (e.g. 512m)")
flags.String("memory-limit", "", "memory limit (e.g. 512m)")
flags.String("cpu-reservation", "", "number of CPU cores reserved (e.g. 0.5)")
flags.String("cpu-limit", "", "CPU cores limit (e.g. 0.5)")
flags.String("generic-resources", "", "user defined resources request (e.g. gpu=3,fpga=1)")
flags.StringSlice("ulimit", []string{}, "ulimit options")
flags.Uint64("update-parallelism", 0, "task update parallelism (0 = all at once)")
flags.String("update-delay", "0s", "delay between task updates (0s = none)")
flags.String("update-on-failure", "pause", "action on failure during update (pause|continue|rollback)")
flags.String("update-order", "stop-first", "order of shutting down old task and starting updated task (stop-first|start-first)")
flags.Uint64("rollback-parallelism", 0, "task update parallelism during rollback (0 = all at once)")
flags.String("rollback-delay", "0s", "delay between task updates during rollback (0s = none)")
flags.String("rollback-on-failure", "pause", "action on failure during rollback (pause|continue)")
flags.String("rollback-order", "stop-first", "order of shutting down old task and starting rolled-back task (stop-first|start-first)")
flags.String("restart-condition", "any", "condition to restart the task (any, failure, none)")
flags.String("restart-delay", "5s", "delay between task restarts")
flags.Uint64("restart-max-attempts", 0, "maximum number of restart attempts (0 = unlimited)")
flags.String("restart-window", "0s", "time window to evaluate restart attempts (0 = unbound)")
flags.Int64("oom-score-adj", 0, "oom score adjustment (-1000 to 1000)")
flags.StringSlice("constraint", nil, "Placement constraint (e.g. node.labels.key==value)")
// TODO(stevvooe): Replace these with a more interesting mount flag.
flags.StringSlice("bind", nil, "define a bind mount")
flags.StringSlice("volume", nil, "define a volume mount")
flags.StringSlice("tmpfs", nil, "define a tmpfs mount")
flags.StringSlice("npipe", nil, "define a npipe mount")
flags.String("log-driver", "", "specify a log driver")
flags.StringSlice("log-opt", nil, "log driver options, as key value pairs")
flags.Bool("init", false, "Run an init inside the container that forwards signals and reaps processes")
}
// Merge merges a flagset into a service spec.
func Merge(cmd *cobra.Command, spec *api.ServiceSpec, c api.ControlClient) error {
flags := cmd.Flags()
if flags.Changed("force") {
force, err := flags.GetBool("force")
if err != nil {
return err
}
if force {
spec.Task.ForceUpdate++
}
}
if flags.Changed("name") {
name, err := flags.GetString("name")
if err != nil {
return err
}
spec.Annotations.Name = name
}
if flags.Changed("label") {
labels, err := flags.GetStringSlice("label")
if err != nil {
return err
}
spec.Annotations.Labels = map[string]string{}
for _, l := range labels {
parts := strings.SplitN(l, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("malformed label: %s", l)
}
spec.Annotations.Labels[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}
}
if err := parseMode(flags, spec); err != nil {
return err
}
if err := parseContainer(flags, spec); err != nil {
return err
}
if err := parseResource(flags, spec); err != nil {
return err
}
if err := parsePorts(flags, spec); err != nil {
return err
}
if err := parseNetworks(cmd, spec, c); err != nil {
return err
}
if err := parseRestart(flags, spec); err != nil {
return err
}
if err := parseUpdate(flags, spec); err != nil {
return err
}
if err := parsePlacement(flags, spec); err != nil {
return err
}
if err := parseBind(flags, spec); err != nil {
return err
}
if err := parseVolume(flags, spec); err != nil {
return err
}
if err := parseTmpfs(flags, spec); err != nil {
return err
}
if err := parseNpipe(flags, spec); err != nil {
return err
}
driver, err := common.ParseLogDriverFlags(flags)
if err != nil {
return err
}
spec.Task.LogDriver = driver
return nil
}