| package container |
| |
| import ( |
| "fmt" |
| "io" |
| |
| "golang.org/x/net/context" |
| |
| "github.com/docker/docker/api/types" |
| "github.com/docker/docker/cli" |
| "github.com/docker/docker/cli/command" |
| "github.com/docker/docker/pkg/stdcopy" |
| "github.com/spf13/cobra" |
| ) |
| |
| var validDrivers = map[string]bool{ |
| "json-file": true, |
| "journald": true, |
| } |
| |
| type logsOptions struct { |
| follow bool |
| since string |
| timestamps bool |
| details bool |
| tail string |
| |
| container string |
| } |
| |
| // NewLogsCommand creates a new cobra.Command for `docker logs` |
| func NewLogsCommand(dockerCli *command.DockerCli) *cobra.Command { |
| var opts logsOptions |
| |
| cmd := &cobra.Command{ |
| Use: "logs [OPTIONS] CONTAINER", |
| Short: "Fetch the logs of a container", |
| Args: cli.ExactArgs(1), |
| RunE: func(cmd *cobra.Command, args []string) error { |
| opts.container = args[0] |
| return runLogs(dockerCli, &opts) |
| }, |
| } |
| |
| flags := cmd.Flags() |
| flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output") |
| flags.StringVar(&opts.since, "since", "", "Show logs since timestamp") |
| flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps") |
| flags.BoolVar(&opts.details, "details", false, "Show extra details provided to logs") |
| flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs") |
| return cmd |
| } |
| |
| 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 |
| } |