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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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()) }
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 }
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) }
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 }
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) }
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 }
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 }
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) }
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) }
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 }
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 }
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 }
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) }
// 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 }
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) }
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) }
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) }
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) }
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) }
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 }
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 }
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 }