コード例 #1
0
ファイル: login.go プロジェクト: CheggEng/docker
func runLogin(dockerCli *client.DockerCli, opts loginOptions) error {
	ctx := context.Background()
	clnt := dockerCli.Client()

	var serverAddress string
	var isDefaultRegistry bool
	if opts.serverAddress != "" {
		serverAddress = opts.serverAddress
	} else {
		serverAddress = dockerCli.ElectAuthServer(ctx)
		isDefaultRegistry = true
	}
	authConfig, err := dockerCli.ConfigureAuth(opts.user, opts.password, serverAddress, isDefaultRegistry)
	if err != nil {
		return err
	}
	response, err := clnt.RegistryLogin(ctx, authConfig)
	if err != nil {
		return err
	}
	if response.IdentityToken != "" {
		authConfig.Password = ""
		authConfig.IdentityToken = response.IdentityToken
	}
	if err := client.StoreCredentials(dockerCli.ConfigFile(), authConfig); err != nil {
		return fmt.Errorf("Error saving credentials: %v", err)
	}

	if response.Status != "" {
		fmt.Fprintln(dockerCli.Out(), response.Status)
	}
	return nil
}
コード例 #2
0
ファイル: remove.go プロジェクト: HuKeping/docker
func runRemove(dockerCli *client.DockerCli, opts removeOptions, images []string) error {
	client := dockerCli.Client()
	ctx := context.Background()

	options := types.ImageRemoveOptions{
		Force:         opts.force,
		PruneChildren: !opts.noPrune,
	}

	var errs []string
	for _, image := range images {
		dels, err := client.ImageRemove(ctx, image, options)
		if err != nil {
			errs = append(errs, err.Error())
		} else {
			for _, del := range dels {
				if del.Deleted != "" {
					fmt.Fprintf(dockerCli.Out(), "Deleted: %s\n", del.Deleted)
				} else {
					fmt.Fprintf(dockerCli.Out(), "Untagged: %s\n", del.Untagged)
				}
			}
		}
	}

	if len(errs) > 0 {
		return fmt.Errorf("%s", strings.Join(errs, "\n"))
	}
	return nil
}
コード例 #3
0
ファイル: list.go プロジェクト: Djelibeybi/docker
func runList(dockerCli *client.DockerCli, opts listOptions) error {
	ctx := context.Background()
	client := dockerCli.Client()

	services, err := client.ServiceList(ctx, types.ServiceListOptions{Filter: opts.filter.Value()})
	if err != nil {
		return err
	}

	out := dockerCli.Out()
	if opts.quiet {
		PrintQuiet(out, services)
	} else {
		taskFilter := filters.NewArgs()
		for _, service := range services {
			taskFilter.Add("service", service.ID)
		}

		tasks, err := client.TaskList(ctx, types.TaskListOptions{Filter: taskFilter})
		if err != nil {
			return err
		}

		nodes, err := client.NodeList(ctx, types.NodeListOptions{})
		if err != nil {
			return err
		}

		PrintNotQuiet(out, services, nodes, tasks)
	}
	return nil
}
コード例 #4
0
ファイル: logs.go プロジェクト: CheggEng/docker
func runLogs(dockerCli *client.DockerCli, opts *logsOptions) error {
	ctx := context.Background()

	c, err := dockerCli.Client().ContainerInspect(ctx, opts.container)
	if err != nil {
		return err
	}

	if !validDrivers[c.HostConfig.LogConfig.Type] {
		return fmt.Errorf("\"logs\" command is supported only for \"json-file\" and \"journald\" logging drivers (got: %s)", c.HostConfig.LogConfig.Type)
	}

	options := types.ContainerLogsOptions{
		ShowStdout: true,
		ShowStderr: true,
		Since:      opts.since,
		Timestamps: opts.timestamps,
		Follow:     opts.follow,
		Tail:       opts.tail,
		Details:    opts.details,
	}
	responseBody, err := dockerCli.Client().ContainerLogs(ctx, opts.container, options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	if c.Config.Tty {
		_, err = io.Copy(dockerCli.Out(), responseBody)
	} else {
		_, err = stdcopy.StdCopy(dockerCli.Out(), dockerCli.Err(), responseBody)
	}
	return err
}
コード例 #5
0
ファイル: create.go プロジェクト: Raphaeljunior/docker
func runCreate(dockerCli *client.DockerCli, opts *serviceOptions) error {
	apiClient := dockerCli.Client()
	createOpts := types.ServiceCreateOptions{}

	service, err := opts.ToService()
	if err != nil {
		return err
	}

	ctx := context.Background()

	// only send auth if flag was set
	if opts.registryAuth {
		// Retrieve encoded auth token from the image reference
		encodedAuth, err := dockerCli.RetrieveAuthTokenFromImage(ctx, opts.image)
		if err != nil {
			return err
		}
		createOpts.EncodedRegistryAuth = encodedAuth
	}

	response, err := apiClient.ServiceCreate(ctx, service, createOpts)
	if err != nil {
		return err
	}

	fmt.Fprintf(dockerCli.Out(), "%s\n", response.ID)
	return nil
}
コード例 #6
0
ファイル: create.go プロジェクト: CheggEng/docker
func runCreate(dockerCli *client.DockerCli, opts createOptions) error {
	client := dockerCli.Client()

	ipamCfg, err := consolidateIpam(opts.ipamSubnet, opts.ipamIPRange, opts.ipamGateway, opts.ipamAux.GetAll())
	if err != nil {
		return err
	}

	// Construct network create request body
	nc := types.NetworkCreate{
		Driver:  opts.driver,
		Options: opts.driverOpts.GetAll(),
		IPAM: network.IPAM{
			Driver:  opts.ipamDriver,
			Config:  ipamCfg,
			Options: opts.ipamOpt.GetAll(),
		},
		CheckDuplicate: true,
		Internal:       opts.internal,
		EnableIPv6:     opts.ipv6,
		Labels:         runconfigopts.ConvertKVStringsToMap(opts.labels),
	}

	resp, err := client.NetworkCreate(context.Background(), opts.name, nc)
	if err != nil {
		return err
	}
	fmt.Fprintf(dockerCli.Out(), "%s\n", resp.ID)
	return nil
}
コード例 #7
0
ファイル: remove.go プロジェクト: maxim28/docker
func runRemove(dockerCli *client.DockerCli, opts *rmOptions) error {
	ctx := context.Background()

	var errs cli.Errors
	for _, name := range opts.plugins {
		named, err := reference.ParseNamed(name) // FIXME: validate
		if err != nil {
			return err
		}
		if reference.IsNameOnly(named) {
			named = reference.WithDefaultTag(named)
		}
		ref, ok := named.(reference.NamedTagged)
		if !ok {
			return fmt.Errorf("invalid name: %s", named.String())
		}
		// TODO: pass names to api instead of making multiple api calls
		if err := dockerCli.Client().PluginRemove(ctx, ref.String(), types.PluginRemoveOptions{Force: opts.force}); err != nil {
			errs = append(errs, err)
			continue
		}
		fmt.Fprintln(dockerCli.Out(), name)
	}
	// Do not simplify to `return errs` because even if errs == nil, it is not a nil-error interface value.
	if errs != nil {
		return errs
	}
	return nil
}
コード例 #8
0
ファイル: load.go プロジェクト: F21/docker
func runLoad(dockerCli *client.DockerCli, opts loadOptions) error {

	var input io.Reader = dockerCli.In()
	if opts.input != "" {
		file, err := os.Open(opts.input)
		if err != nil {
			return err
		}
		defer file.Close()
		input = file
	}
	if !dockerCli.IsTerminalOut() {
		opts.quiet = true
	}
	response, err := dockerCli.Client().ImageLoad(context.Background(), input, opts.quiet)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.Body != nil && response.JSON {
		return jsonmessage.DisplayJSONMessagesStream(response.Body, dockerCli.Out(), dockerCli.OutFd(), dockerCli.IsTerminalOut(), nil)
	}

	_, err = io.Copy(dockerCli.Out(), response.Body)
	return err
}
コード例 #9
0
ファイル: events.go プロジェクト: alexmavr/docker
func runEvents(dockerCli *client.DockerCli, opts *eventsOptions) error {
	eventFilterArgs := filters.NewArgs()

	// Consolidate all filter flags, and sanity check them early.
	// They'll get process in the daemon/server.
	for _, f := range opts.filter {
		var err error
		eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
		if err != nil {
			return err
		}
	}

	options := types.EventsOptions{
		Since:   opts.since,
		Until:   opts.until,
		Filters: eventFilterArgs,
	}

	responseBody, err := dockerCli.Client().Events(context.Background(), options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return streamEvents(responseBody, dockerCli.Out())
}
コード例 #10
0
func runDiff(dockerCli *client.DockerCli, opts *diffOptions) error {
	if opts.container == "" {
		return fmt.Errorf("Container name cannot be empty")
	}
	ctx := context.Background()

	changes, err := dockerCli.Client().ContainerDiff(ctx, opts.container)
	if err != nil {
		return err
	}

	for _, change := range changes {
		var kind string
		switch change.Kind {
		case archive.ChangeModify:
			kind = "C"
		case archive.ChangeAdd:
			kind = "A"
		case archive.ChangeDelete:
			kind = "D"
		}
		fmt.Fprintf(dockerCli.Out(), "%s %s\n", kind, change.Path)
	}

	return nil
}
コード例 #11
0
ファイル: inspect.go プロジェクト: maxim28/docker
func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
	ctx := context.Background()
	client := dockerCli.Client()

	var getRefFunc inspect.GetRefFunc
	switch opts.inspectType {
	case "container":
		getRefFunc = func(ref string) (interface{}, []byte, error) {
			return client.ContainerInspectWithRaw(ctx, ref, opts.size)
		}
	case "image":
		getRefFunc = func(ref string) (interface{}, []byte, error) {
			return client.ImageInspectWithRaw(ctx, ref)
		}
	case "task":
		if opts.size {
			fmt.Fprintln(dockerCli.Err(), "WARNING: --size ignored for tasks")
		}
		getRefFunc = func(ref string) (interface{}, []byte, error) {
			return client.TaskInspectWithRaw(ctx, ref)
		}
	case "":
		getRefFunc = inspectAll(ctx, dockerCli, opts.size)
	default:
		return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
	}

	return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, getRefFunc)
}
コード例 #12
0
ファイル: scale.go プロジェクト: karunchennuri/docker
func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string) error {
	client := dockerCli.Client()
	ctx := context.Background()

	service, err := client.ServiceInspect(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")
	}
	uintScale, err := strconv.ParseUint(scale, 10, 64)
	if err != nil {
		return fmt.Errorf("invalid replicas value %s: %s", scale, err.Error())
	}
	serviceMode.Replicated.Replicas = &uintScale

	err = client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec)
	if err != nil {
		return err
	}

	fmt.Fprintf(dockerCli.Out(), "%s scaled to %s\n", serviceID, scale)
	return nil
}
コード例 #13
0
ファイル: push.go プロジェクト: FlyingShit-XinHuang/docker
func runPush(dockerCli *client.DockerCli, remote string) error {
	ref, err := reference.ParseNamed(remote)
	if err != nil {
		return err
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}

	ctx := context.Background()

	// Resolve the Auth config relevant for this server
	authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index)
	requestPrivilege := dockerCli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "push")

	if client.IsTrusted() {
		return dockerCli.TrustedPush(ctx, repoInfo, ref, authConfig, requestPrivilege)
	}

	responseBody, err := dockerCli.ImagePushPrivileged(ctx, authConfig, ref.String(), requestPrivilege)
	if err != nil {
		return err
	}

	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, dockerCli.Out(), dockerCli.OutFd(), dockerCli.IsTerminalOut(), nil)
}
コード例 #14
0
ファイル: update.go プロジェクト: rlugojr/docker
func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts swarmOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	var updateFlags swarm.UpdateFlags

	swarm, err := client.SwarmInspect(ctx)
	if err != nil {
		return err
	}

	err = mergeSwarm(&swarm, flags)
	if err != nil {
		return err
	}

	err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec, updateFlags)
	if err != nil {
		return err
	}

	fmt.Fprintln(dockerCli.Out(), "Swarm updated.")

	return nil
}
コード例 #15
0
ファイル: init.go プロジェクト: alexmavr/docker
func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	req := swarm.InitRequest{
		ListenAddr:      opts.listenAddr.String(),
		AdvertiseAddr:   opts.advertiseAddr,
		ForceNewCluster: opts.forceNewCluster,
		Spec:            opts.swarmOptions.ToSpec(),
	}

	nodeID, err := client.SwarmInit(ctx, req)
	if err != nil {
		if strings.Contains(err.Error(), "could not choose an IP address to advertise") || strings.Contains(err.Error(), "could not find the system's IP address") {
			return errors.New(err.Error() + " - specify one with --advertise-addr")
		}
		return err
	}

	fmt.Fprintf(dockerCli.Out(), "Swarm initialized: current node (%s) is now a manager.\n\n", nodeID)

	if err := printJoinCommand(ctx, dockerCli, nodeID, true, false); err != nil {
		return err
	}

	fmt.Fprint(dockerCli.Out(), "To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.\n\n")
	return nil
}
コード例 #16
0
ファイル: create.go プロジェクト: alexmavr/docker
func pullImage(ctx context.Context, dockerCli *client.DockerCli, image string, out io.Writer) error {
	ref, err := reference.ParseNamed(image)
	if err != nil {
		return err
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}

	authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index)
	encodedAuth, err := client.EncodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	options := types.ImageCreateOptions{
		RegistryAuth: encodedAuth,
	}

	responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(
		responseBody,
		out,
		dockerCli.Out().FD(),
		dockerCli.Out().IsTerminal(),
		nil)
}
コード例 #17
0
ファイル: config.go プロジェクト: CrocdileChan/docker
func runConfig(dockerCli *client.DockerCli, opts configOptions) error {
	bundle, err := loadBundlefile(dockerCli.Err(), opts.namespace, opts.bundlefile)
	if err != nil {
		return err
	}
	return bundlefile.Print(dockerCli.Out(), bundle)
}
コード例 #18
0
ファイル: list.go プロジェクト: FlyingShit-XinHuang/docker
func runList(dockerCli *client.DockerCli, opts listOptions) error {
	ctx := context.Background()
	client := dockerCli.Client()

	services, err := client.ServiceList(ctx, types.ServiceListOptions{Filter: opts.filter.Value()})
	if err != nil {
		return err
	}

	out := dockerCli.Out()
	if opts.quiet {
		printQuiet(out, services)
	} else {
		taskFilter := filters.NewArgs()
		for _, service := range services {
			taskFilter.Add("service", service.ID)
		}

		tasks, err := client.TaskList(ctx, types.TaskListOptions{Filter: taskFilter})
		if err != nil {
			return err
		}

		running := map[string]int{}
		for _, task := range tasks {
			if task.Status.State == "running" {
				running[task.ServiceID]++
			}
		}

		printTable(out, services, running)
	}
	return nil
}
コード例 #19
0
ファイル: commit.go プロジェクト: Raphaeljunior/docker
func runCommit(dockerCli *client.DockerCli, opts *commitOptions) error {
	ctx := context.Background()

	name := opts.container
	reference := opts.reference

	var config *containertypes.Config
	if opts.config != "" {
		config = &containertypes.Config{}
		if err := json.Unmarshal([]byte(opts.config), config); err != nil {
			return err
		}
	}

	options := types.ContainerCommitOptions{
		Reference: reference,
		Comment:   opts.comment,
		Author:    opts.author,
		Changes:   opts.changes.GetAll(),
		Pause:     opts.pause,
		Config:    config,
	}

	response, err := dockerCli.Client().ContainerCommit(ctx, name, options)
	if err != nil {
		return err
	}

	fmt.Fprintln(dockerCli.Out(), response.ID)
	return nil
}
コード例 #20
0
ファイル: join.go プロジェクト: ygf11/docker
func runJoin(dockerCli *client.DockerCli, opts joinOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	req := swarm.JoinRequest{
		JoinToken:   opts.token,
		ListenAddr:  opts.listenAddr.String(),
		RemoteAddrs: []string{opts.remote},
	}
	err := client.SwarmJoin(ctx, req)
	if err != nil {
		return err
	}

	info, err := client.Info(ctx)
	if err != nil {
		return err
	}

	_, _, err = client.NodeInspectWithRaw(ctx, info.Swarm.NodeID)
	if err != nil {
		// TODO(aaronl): is there a better way to do this?
		if strings.Contains(err.Error(), "This node is not a swarm manager.") {
			fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a worker.")
		}
	} else {
		fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a manager.")
	}

	return nil
}
コード例 #21
0
ファイル: promote.go プロジェクト: CheggEng/docker
func runPromote(dockerCli *client.DockerCli, nodes []string) error {
	promote := func(node *swarm.Node) {
		node.Spec.Role = swarm.NodeRoleManager
	}
	success := func(nodeID string) {
		fmt.Fprintf(dockerCli.Out(), "Node %s promoted to a manager in the swarm.\n", nodeID)
	}
	return updateNodes(dockerCli, nodes, promote, success)
}
コード例 #22
0
ファイル: print.go プロジェクト: maxim28/docker
// Print task information in a table format
func Print(dockerCli *client.DockerCli, ctx context.Context, tasks []swarm.Task, resolver *idresolver.IDResolver, noTrunc bool) error {
	sort.Stable(tasksBySlot(tasks))

	writer := tabwriter.NewWriter(dockerCli.Out(), 0, 4, 2, ' ', 0)

	// Ignore flushing errors
	defer writer.Flush()
	fmt.Fprintln(writer, strings.Join([]string{"ID", "NAME", "IMAGE", "NODE", "DESIRED STATE", "CURRENT STATE", "ERROR"}, "\t"))

	prevName := ""
	for _, task := range tasks {
		serviceValue, err := resolver.Resolve(ctx, swarm.Service{}, task.ServiceID)
		if err != nil {
			return err
		}
		nodeValue, err := resolver.Resolve(ctx, swarm.Node{}, task.NodeID)
		if err != nil {
			return err
		}

		name := serviceValue
		if task.Slot > 0 {
			name = fmt.Sprintf("%s.%d", name, task.Slot)
		}

		// Indent the name if necessary
		indentedName := name
		if prevName == name {
			indentedName = fmt.Sprintf(" \\_ %s", indentedName)
		}
		prevName = name

		// Trim and quote the error message.
		taskErr := task.Status.Err
		if !noTrunc && len(taskErr) > maxErrLength {
			taskErr = fmt.Sprintf("%s…", taskErr[:maxErrLength-1])
		}
		if len(taskErr) > 0 {
			taskErr = fmt.Sprintf("\"%s\"", taskErr)
		}

		fmt.Fprintf(
			writer,
			psTaskItemFmt,
			task.ID,
			indentedName,
			task.Spec.ContainerSpec.Image,
			nodeValue,
			client.PrettyPrint(task.DesiredState),
			client.PrettyPrint(task.Status.State),
			strings.ToLower(units.HumanDuration(time.Since(task.Status.Timestamp))),
			taskErr,
		)
	}

	return nil
}
コード例 #23
0
ファイル: inspect.go プロジェクト: kolyshkin/docker
func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
	client := dockerCli.Client()

	getNetFunc := func(name string) (interface{}, []byte, error) {
		return client.NetworkInspectWithRaw(context.Background(), name)
	}

	return inspect.Inspect(dockerCli.Out(), opts.names, opts.format, getNetFunc)
}
コード例 #24
0
ファイル: demote.go プロジェクト: CrocdileChan/docker
func runDemote(dockerCli *client.DockerCli, nodes []string) error {
	demote := func(node *swarm.Node) {
		node.Spec.Role = swarm.NodeRoleWorker
	}
	success := func(nodeID string) {
		fmt.Fprintf(dockerCli.Out(), "Manager %s demoted in the swarm.\n", nodeID)
	}
	return updateNodes(dockerCli, nodes, demote, success)
}
コード例 #25
0
ファイル: accept.go プロジェクト: CheggEng/docker
func runAccept(dockerCli *client.DockerCli, nodes []string) error {
	accept := func(node *swarm.Node) {
		node.Spec.Membership = swarm.NodeMembershipAccepted
	}
	success := func(nodeID string) {
		fmt.Fprintf(dockerCli.Out(), "Node %s accepted in the swarm.\n", nodeID)
	}
	return updateNodes(dockerCli, nodes, accept, success)
}
コード例 #26
0
ファイル: inspect.go プロジェクト: HuKeping/docker
func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
	var elementSearcher inspect.GetRefFunc
	switch opts.inspectType {
	case "", "container", "image", "node", "network", "service", "volume", "task":
		elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
	default:
		return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
	}
	return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher)
}
コード例 #27
0
ファイル: inspect.go プロジェクト: kolyshkin/docker
func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
	client := dockerCli.Client()

	getVolFunc := func(name string) (interface{}, []byte, error) {
		i, err := client.VolumeInspect(context.Background(), name)
		return i, nil, err
	}

	return inspect.Inspect(dockerCli.Out(), opts.names, opts.format, getVolFunc)
}
コード例 #28
0
ファイル: info.go プロジェクト: alexmavr/docker
func formatInfo(dockerCli *client.DockerCli, info types.Info, format string) error {
	tmpl, err := templates.Parse(format)
	if err != nil {
		return cli.StatusError{StatusCode: 64,
			Status: "Template parsing error: " + err.Error()}
	}
	err = tmpl.Execute(dockerCli.Out(), info)
	dockerCli.Out().Write([]byte{'\n'})
	return err
}
コード例 #29
0
ファイル: leave.go プロジェクト: CrocdileChan/docker
func runLeave(dockerCli *client.DockerCli, opts leaveOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	if err := client.SwarmLeave(ctx, opts.force); err != nil {
		return err
	}

	fmt.Fprintln(dockerCli.Out(), "Node left the swarm.")
	return nil
}
コード例 #30
0
ファイル: promote.go プロジェクト: johnstevin/docker
func runPromote(dockerCli *client.DockerCli, flags *pflag.FlagSet, args []string) error {
	for _, id := range args {
		if err := runUpdate(dockerCli, id, func(node *swarm.Node) {
			node.Spec.Role = swarm.NodeRoleManager
		}); err != nil {
			return err
		}
		fmt.Fprintf(dockerCli.Out(), "Node %s promoted to a manager in the swarm.", id)
	}

	return nil
}