func runSecretCreate(dockerCli *command.DockerCli, options createOptions) error { client := dockerCli.Client() ctx := context.Background() secretData, err := ioutil.ReadAll(os.Stdin) if err != nil { return fmt.Errorf("Error reading content from STDIN: %v", err) } spec := swarm.SecretSpec{ Annotations: swarm.Annotations{ Name: options.name, Labels: runconfigopts.ConvertKVStringsToMap(options.labels.GetAll()), }, Data: secretData, } r, err := client.SecretCreate(ctx, spec) if err != nil { return err } fmt.Fprintln(dockerCli.Out(), r.ID) return nil }
func runConfig(dockerCli *command.DockerCli, opts configOptions) error { bundle, err := loadBundlefile(dockerCli.Err(), opts.namespace, opts.bundlefile) if err != nil { return err } return bundlefile.Print(dockerCli.Out(), bundle) }
// NewPruneCommand returns a new cobra prune command for networks func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { opts := pruneOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ Use: "prune [OPTIONS]", Short: "Remove all unused networks", Args: cli.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { output, err := runPrune(dockerCli, opts) if err != nil { return err } if output != "" { fmt.Fprintln(dockerCli.Out(), output) } return nil }, Tags: map[string]string{"version": "1.25"}, } flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'until=<timestamp>')") return cmd }
func runCreate(dockerCli *command.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 := command.RetrieveAuthTokenFromImage(ctx, dockerCli, 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 }
// NewPruneCommand returns a new cobra prune command for volumes func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { var opts pruneOptions cmd := &cobra.Command{ Use: "prune [OPTIONS]", Short: "Remove all unused volumes", Args: cli.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { spaceReclaimed, output, err := runPrune(dockerCli, opts) if err != nil { return err } if output != "" { fmt.Fprintln(dockerCli.Out(), output) } fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) return nil }, } flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") return cmd }
func runDiff(dockerCli *command.DockerCli, opts *diffOptions) error { if opts.container == "" { return errors.New("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.Fprintln(dockerCli.Out(), kind, change.Path) } return nil }
// NewPruneCommand returns a new cobra prune command for images func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { opts := pruneOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ Use: "prune [OPTIONS]", Short: "Remove unused images", Args: cli.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { spaceReclaimed, output, err := runPrune(dockerCli, opts) if err != nil { return err } if output != "" { fmt.Fprintln(dockerCli.Out(), output) } fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) return nil }, Tags: map[string]string{"version": "1.25"}, } flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") flags.BoolVarP(&opts.all, "all", "a", false, "Remove all unused images, not just dangling ones") flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'until=<timestamp>')") return cmd }
func runLogs(dockerCli *command.DockerCli, opts *logsOptions) error { ctx := context.Background() options := types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Since: opts.since, Timestamps: opts.timestamps, Follow: opts.follow, Tail: opts.tail, Details: opts.details, } client := dockerCli.Client() responseBody, err := client.ServiceLogs(ctx, opts.service, options) if err != nil { return err } defer responseBody.Close() resolver := idresolver.New(client, opts.noResolve) stdout := &logWriter{ctx: ctx, opts: opts, r: resolver, w: dockerCli.Out()} stderr := &logWriter{ctx: ctx, opts: opts, r: resolver, w: dockerCli.Err()} // TODO(aluzzardi): Do an io.Copy for services with TTY enabled. _, err = stdcopy.StdCopy(stdout, stderr, responseBody) return err }
func runLogs(dockerCli *command.DockerCli, opts *logsOptions) error { ctx := context.Background() 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() c, err := dockerCli.Client().ContainerInspect(ctx, opts.container) if err != nil { return err } if c.Config.Tty { _, err = io.Copy(dockerCli.Out(), responseBody) } else { _, err = stdcopy.StdCopy(dockerCli.Out(), dockerCli.Err(), responseBody) } return err }
func runList(dockerCli *command.DockerCli, opts listOptions) error { client := dockerCli.Client() options := types.NetworkListOptions{Filters: opts.filter.Value()} networkResources, err := client.NetworkList(context.Background(), options) if err != nil { return err } format := opts.format if len(format) == 0 { if len(dockerCli.ConfigFile().NetworksFormat) > 0 && !opts.quiet { format = dockerCli.ConfigFile().NetworksFormat } else { format = formatter.TableFormatKey } } sort.Sort(byNetworkName(networkResources)) networksCtx := formatter.Context{ Output: dockerCli.Out(), Format: formatter.NewNetworkFormat(format, opts.quiet), Trunc: !opts.noTrunc, } return formatter.NetworkWrite(networksCtx, networkResources) }
func runCreate(dockerCli *command.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, Attachable: opts.attachable, 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 runUpdate(dockerCli *command.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 } prevAutoLock := swarm.Spec.EncryptionConfig.AutoLockManagers opts.mergeSwarmSpec(&swarm.Spec, flags) curAutoLock := swarm.Spec.EncryptionConfig.AutoLockManagers err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec, updateFlags) if err != nil { return err } fmt.Fprintln(dockerCli.Out(), "Swarm updated.") if curAutoLock && !prevAutoLock { unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) if err != nil { return errors.Wrap(err, "could not fetch unlock key") } printUnlockCommand(ctx, dockerCli, unlockKeyResp.UnlockKey) } return nil }
func runPs(dockerCli *command.DockerCli, opts *psOptions) error { ctx := context.Background() listOptions, err := buildContainerListOptions(opts) if err != nil { return err } containers, err := dockerCli.Client().ContainerList(ctx, *listOptions) if err != nil { return err } format := opts.format if len(format) == 0 { if len(dockerCli.ConfigFile().PsFormat) > 0 && !opts.quiet { format = dockerCli.ConfigFile().PsFormat } else { format = formatter.TableFormatKey } } containerCtx := formatter.Context{ Output: dockerCli.Out(), Format: formatter.NewContainerFormat(format, opts.quiet, listOptions.Size), Trunc: !opts.noTrunc, } return formatter.ContainerWrite(containerCtx, containers) }
func runRm(dockerCli *command.DockerCli, opts *rmOptions) error { ctx := context.Background() var errs []string options := types.ContainerRemoveOptions{ RemoveVolumes: opts.rmVolumes, RemoveLinks: opts.rmLink, Force: opts.force, } errChan := parallelOperation(ctx, opts.containers, func(ctx context.Context, container string) error { if container == "" { return fmt.Errorf("Container name cannot be empty") } container = strings.Trim(container, "/") return dockerCli.Client().ContainerRemove(ctx, container, options) }) for _, name := range opts.containers { if err := <-errChan; err != nil { errs = append(errs, err.Error()) } else { fmt.Fprintf(dockerCli.Out(), "%s\n", name) } } if len(errs) > 0 { return fmt.Errorf("%s", strings.Join(errs, "\n")) } return nil }
func runServiceScale(dockerCli *command.DockerCli, serviceID string, scale string) 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") } 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, types.ServiceUpdateOptions{}) if err != nil { return err } fmt.Fprintf(dockerCli.Out(), "%s scaled to %s\n", serviceID, scale) return nil }
func runImages(dockerCli *command.DockerCli, opts imagesOptions) error { ctx := context.Background() options := types.ImageListOptions{ MatchName: opts.matchName, All: opts.all, Filters: opts.filter.Value(), } images, err := dockerCli.Client().ImageList(ctx, options) if err != nil { return err } format := opts.format if len(format) == 0 { if len(dockerCli.ConfigFile().ImagesFormat) > 0 && !opts.quiet { format = dockerCli.ConfigFile().ImagesFormat } else { format = formatter.TableFormatKey } } imageCtx := formatter.ImageContext{ Context: formatter.Context{ Output: dockerCli.Out(), Format: formatter.NewImageFormat(format, opts.quiet, opts.showDigests), Trunc: !opts.noTrunc, }, Digest: opts.showDigests, } return formatter.ImageWrite(imageCtx, images) }
func pullImage(ctx context.Context, dockerCli *command.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 := command.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) }
// TrustedReference returns the canonical trusted reference for an image reference func TrustedReference(ctx context.Context, cli *command.DockerCli, ref reference.NamedTagged) (reference.Canonical, error) { repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return nil, err } // Resolve the Auth config relevant for this server authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index) notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull") if err != nil { fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err) return nil, err } t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole) if err != nil { return nil, err } // Only list tags in the top level targets role or the releases delegation role - ignore // all other delegation roles if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole { return nil, trust.NotaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.Tag())) } r, err := convertTarget(t.Target) if err != nil { return nil, err } return reference.WithDigest(reference.TrimNamed(ref), r.digest) }
func runStop(dockerCli *command.DockerCli, opts *stopOptions) error { ctx := context.Background() var timeout *time.Duration if opts.timeChanged { timeoutValue := time.Duration(opts.time) * time.Second timeout = &timeoutValue } var errs []string errChan := parallelOperation(ctx, opts.containers, func(ctx context.Context, id string) error { return dockerCli.Client().ContainerStop(ctx, id, timeout) }) for _, container := range opts.containers { if err := <-errChan; err != nil { errs = append(errs, err.Error()) } else { fmt.Fprintf(dockerCli.Out(), "%s\n", container) } } if len(errs) > 0 { return fmt.Errorf("%s", strings.Join(errs, "\n")) } return nil }
func runLogs(dockerCli *command.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 runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) { pruneFilters := opts.filter.Value() pruneFilters.Add("dangling", fmt.Sprintf("%v", !opts.all)) warning := danglingWarning if opts.all { warning = allImageWarning } if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) { return } report, err := dockerCli.Client().ImagesPrune(context.Background(), pruneFilters) if err != nil { return } if len(report.ImagesDeleted) > 0 { output = "Deleted Images:\n" for _, st := range report.ImagesDeleted { if st.Untagged != "" { output += fmt.Sprintln("untagged:", st.Untagged) } else { output += fmt.Sprintln("deleted:", st.Deleted) } } spaceReclaimed = report.SpaceReclaimed } return }
func runSecretCreate(dockerCli *command.DockerCli, options createOptions) error { client := dockerCli.Client() ctx := context.Background() var in io.Reader = dockerCli.In() if options.file != "-" { file, err := system.OpenSequential(options.file) if err != nil { return err } in = file defer file.Close() } secretData, err := ioutil.ReadAll(in) if err != nil { return fmt.Errorf("Error reading content from %q: %v", options.file, err) } spec := swarm.SecretSpec{ Annotations: swarm.Annotations{ Name: options.name, Labels: runconfigopts.ConvertKVStringsToMap(options.labels.GetAll()), }, Data: secretData, } r, err := client.SecretCreate(ctx, spec) if err != nil { return err } fmt.Fprintln(dockerCli.Out(), r.ID) return nil }
func runEvents(dockerCli *command.DockerCli, opts *eventsOptions) error { tmpl, err := makeTemplate(opts.format) if err != nil { return cli.StatusError{ StatusCode: 64, Status: "Error parsing format: " + err.Error()} } options := types.EventsOptions{ Since: opts.since, Until: opts.until, Filters: opts.filter.Value(), } ctx, cancel := context.WithCancel(context.Background()) events, errs := dockerCli.Client().Events(ctx, options) defer cancel() out := dockerCli.Out() for { select { case event := <-events: if err := handleEvent(out, event, tmpl); err != nil { return err } case err := <-errs: if err == io.EOF { return nil } return err } } }
func runSecretList(dockerCli *command.DockerCli, opts listOptions) error { client := dockerCli.Client() ctx := context.Background() secrets, err := client.SecretList(ctx, types.SecretListOptions{}) if err != nil { return err } w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) if opts.quiet { for _, s := range secrets { fmt.Fprintf(w, "%s\n", s.ID) } } else { fmt.Fprintf(w, "ID\tNAME\tCREATED\tUPDATED\tSIZE") fmt.Fprintf(w, "\n") for _, s := range secrets { created := units.HumanDuration(time.Now().UTC().Sub(s.Meta.CreatedAt)) + " ago" updated := units.HumanDuration(time.Now().UTC().Sub(s.Meta.UpdatedAt)) + " ago" size := units.HumanSizeWithPrecision(float64(s.SecretSize), 3) fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", s.ID, s.Spec.Annotations.Name, created, updated, size) } } w.Flush() return nil }
func runDisable(dockerCli *command.DockerCli, name string, force bool) error { if err := dockerCli.Client().PluginDisable(context.Background(), name, types.PluginDisableOptions{Force: force}); err != nil { return err } fmt.Fprintln(dockerCli.Out(), name) return nil }
func runList(dockerCli *command.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 runPush(dockerCli *command.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 := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push") if command.IsTrusted() { return trustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege) } responseBody, err := imagePushPrivileged(ctx, dockerCli, authConfig, ref.String(), requestPrivilege) if err != nil { return err } defer responseBody.Close() return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil) }
// NewPruneCommand returns a new cobra prune command for networks func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command { var opts pruneOptions cmd := &cobra.Command{ Use: "prune [OPTIONS]", Short: "Remove all unused networks", Args: cli.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { output, err := runPrune(dockerCli, opts) if err != nil { return err } if output != "" { fmt.Fprintln(dockerCli.Out(), output) } return nil }, Tags: map[string]string{"version": "1.25"}, } flags := cmd.Flags() flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation") return cmd }
func runRemove(dockerCli *command.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 runSecretRemove(dockerCli *command.DockerCli, opts removeOptions) error { client := dockerCli.Client() ctx := context.Background() ids, err := getCliRequestedSecretIDs(ctx, client, opts.names) if err != nil { return err } var errs []string for _, id := range ids { if err := client.SecretRemove(ctx, id); err != nil { errs = append(errs, err.Error()) continue } fmt.Fprintln(dockerCli.Out(), id) } if len(errs) > 0 { return fmt.Errorf("%s", strings.Join(errs, "\n")) } return nil }