diff options
author | Urvashi Mohnani <umohnani@redhat.com> | 2017-11-21 12:18:25 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-11-22 19:33:13 +0000 |
commit | ee4051db61ad8ce6f385ce5be45dcc4b0a29945d (patch) | |
tree | 68672ed0247fd43c31447b4d80920b442e0fecc3 /cmd/kpod | |
parent | 40dce698d3359a6bf89ed954a483454daf2e9fb2 (diff) | |
download | podman-ee4051db61ad8ce6f385ce5be45dcc4b0a29945d.tar.gz podman-ee4051db61ad8ce6f385ce5be45dcc4b0a29945d.tar.bz2 podman-ee4051db61ad8ce6f385ce5be45dcc4b0a29945d.zip |
Update kpod logs to use the new container state and runtime
Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
Closes: #62
Approved by: rhatdan
Diffstat (limited to 'cmd/kpod')
-rw-r--r-- | cmd/kpod/logs.go | 105 |
1 files changed, 83 insertions, 22 deletions
diff --git a/cmd/kpod/logs.go b/cmd/kpod/logs.go index 1d0cea996..726ba4a65 100644 --- a/cmd/kpod/logs.go +++ b/cmd/kpod/logs.go @@ -2,13 +2,22 @@ package main import ( "fmt" + "strings" "time" + "github.com/hpcloud/tail" "github.com/pkg/errors" - "github.com/projectatomic/libpod/libkpod" + "github.com/projectatomic/libpod/libpod" "github.com/urfave/cli" ) +type logOptions struct { + details bool + follow bool + sinceTime time.Time + tail uint64 +} + var ( logsFlags = []cli.Flag{ cli.BoolFlag{ @@ -42,51 +51,103 @@ var ( ) func logsCmd(c *cli.Context) error { + if err := validateFlags(c, logsFlags); err != nil { + return err + } + + runtime, err := getRuntime(c) + if err != nil { + return errors.Wrapf(err, "could not get runtime") + } + defer runtime.Shutdown(false) + args := c.Args() if len(args) != 1 { return errors.Errorf("'kpod logs' requires exactly one container name/ID") } - if err := validateFlags(c, logsFlags); err != nil { - return err - } - container := c.Args().First() - var opts libkpod.LogOptions - opts.Details = c.Bool("details") - opts.Follow = c.Bool("follow") - opts.SinceTime = time.Time{} + + sinceTime := time.Time{} if c.IsSet("since") { // parse time, error out if something is wrong since, err := time.Parse("2006-01-02T15:04:05.999999999-07:00", c.String("since")) if err != nil { return errors.Wrapf(err, "could not parse time: %q", c.String("since")) } - opts.SinceTime = since + sinceTime = since } - opts.Tail = c.Uint64("tail") - config, err := getConfig(c) - if err != nil { - return errors.Wrapf(err, "could not get config") + opts := logOptions{ + details: c.Bool("details"), + follow: c.Bool("follow"), + sinceTime: sinceTime, + tail: c.Uint64("tail"), } - server, err := libkpod.New(config) - if err != nil { - return errors.Wrapf(err, "could not create container server") - } - defer server.Shutdown() - err = server.Update() + + ctr, err := runtime.LookupContainer(args[0]) if err != nil { - return errors.Wrapf(err, "could not update list of containers") + return err } + logs := make(chan string) go func() { - err = server.GetLogs(container, logs, opts) + err = getLogs(ctr, logs, opts) }() printLogs(logs) return err } +// getLogs returns the logs of a container from the log file +// log file is created when the container is started/ran +func getLogs(container *libpod.Container, logChan chan string, opts logOptions) error { + defer close(logChan) + + seekInfo := &tail.SeekInfo{Offset: 0, Whence: 0} + if opts.tail > 0 { + // seek to correct position in log files + seekInfo.Offset = int64(opts.tail) + seekInfo.Whence = 2 + } + + t, err := tail.TailFile(container.LogPath(), tail.Config{Follow: opts.follow, ReOpen: false, Location: seekInfo}) + for line := range t.Lines { + if since, err := logSinceTime(opts.sinceTime, line.Text); err != nil || !since { + continue + } + logMessage := line.Text[secondSpaceIndex(line.Text):] + logChan <- logMessage + } + return err +} + func printLogs(logs chan string) { for line := range logs { fmt.Println(line) } } + +// returns true if the time stamps of the logs are equal to or after the +// timestamp comparing to +func logSinceTime(sinceTime time.Time, logStr string) (bool, error) { + timestamp := strings.Split(logStr, " ")[0] + logTime, err := time.Parse("2006-01-02T15:04:05.999999999-07:00", timestamp) + if err != nil { + return false, err + } + return logTime.After(sinceTime) || logTime.Equal(sinceTime), nil +} + +// secondSpaceIndex returns the index of the second space in a string +// In a line of the logs, the first two tokens are a timestamp and stdout/stderr, +// followed by the message itself. This allows us to get the index of the message +// and avoid sending the other information back to the caller of GetLogs() +func secondSpaceIndex(line string) int { + index := strings.Index(line, " ") + if index == -1 { + return 0 + } + index = strings.Index(line[index:], " ") + if index == -1 { + return 0 + } + return index +} |