Skip to content

Commit

Permalink
podman events allow future time for --until
Browse files Browse the repository at this point in the history
The podman events aren't read until the given timestamp if the
timestamp is in the future. It just reads all events until now
and exits afterwards.
This does not make sense and does not match docker. The correct
behavior is to read all events until the given time is reached.

This fixes a bug where the wrong event log file path was used
when running first time with a new storage location.
Fixes #8694

This also fixes the events api endpoint which only exited when
an error occurred. Otherwise it just hung after reading all events.

Signed-off-by: Paul Holzinger <[email protected]>
  • Loading branch information
Paul Holzinger committed Dec 11, 2020
1 parent dd95478 commit 74fcd9f
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 10 deletions.
3 changes: 0 additions & 3 deletions libpod/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,5 @@ func (e EventLogFile) getTail(options ReadOptions) (*tail.Tail, error) {
reopen = false
}
stream := options.Stream
if len(options.Until) > 0 {
stream = false
}
return tail.TailFile(e.options.LogFilePath, tail.Config{ReOpen: reopen, Follow: stream, Location: &seek, Logger: tail.DiscardingLogger, Poll: true})
}
16 changes: 14 additions & 2 deletions libpod/events/journal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"
"time"

"github.com/containers/podman/v2/pkg/util"
"github.com/coreos/go-systemd/v22/journal"
"github.com/coreos/go-systemd/v22/sdjournal"
"github.com/pkg/errors"
Expand Down Expand Up @@ -72,6 +73,13 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return errors.Wrapf(err, "failed to generate event options")
}
var untilTime time.Time
if len(options.Until) > 0 {
untilTime, err = util.ParseInputTime(options.Until)
if err != nil {
return err
}
}
j, err := sdjournal.NewJournal()
if err != nil {
return err
Expand Down Expand Up @@ -122,10 +130,14 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
return errors.Wrap(err, "failed to get journal cursor")
}
if prevCursor == newCursor {
if len(options.Until) > 0 || !options.Stream {
if !options.Stream || (len(options.Until) > 0 && time.Now().After(untilTime)) {
break
}
_ = j.Wait(sdjournal.IndefiniteWait)
t := sdjournal.IndefiniteWait
if len(options.Until) > 0 {
t = time.Until(untilTime)
}
_ = j.Wait(t)
continue
}
prevCursor = newCursor
Expand Down
12 changes: 12 additions & 0 deletions libpod/events/logfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"context"
"fmt"
"os"
"time"

"github.com/containers/podman/v2/pkg/util"
"github.com/containers/storage"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -51,6 +53,16 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return err
}
if len(options.Until) > 0 {
untilTime, err := util.ParseInputTime(options.Until)
if err != nil {
return err
}
go func() {
time.Sleep(time.Until(untilTime))
t.Stop()
}()
}
funcDone := make(chan bool)
copy := true
go func() {
Expand Down
1 change: 1 addition & 0 deletions libpod/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ func WithEventsLogger(logger string) RuntimeOption {
}

rt.config.Engine.EventsLogger = logger
rt.config.Engine.EventsLogFilePath = filepath.Join(rt.config.Engine.TmpDir, "events", "events.log")

return nil
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/api/handlers/compat/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
Until: query.Until,
}
errorChannel <- runtime.Events(r.Context(), readOpts)

}()

var flush = func() {}
Expand All @@ -130,8 +131,8 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
if err != nil {
// FIXME StatusOK already sent above cannot send 500 here
utils.InternalServerError(w, err)
return
}
return
case evt := <-eventChannel:
if evt == nil {
continue
Expand Down
43 changes: 39 additions & 4 deletions test/e2e/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"fmt"
"os"
"strings"
"sync"
"time"

. "github.com/containers/podman/v2/test/utils"
"github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
Expand Down Expand Up @@ -115,10 +117,7 @@ var _ = Describe("Podman events", func() {
SkipIfNotFedora()
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
test := podmanTest.Podman([]string{"events", "--help"})
test.WaitWithDefaultTimeout()
fmt.Println(test.OutputToStringArray())
result := podmanTest.Podman([]string{"events", "--stream=false", "--since", "1h"})
result := podmanTest.Podman([]string{"events", "--stream=false", "--until", "1h"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(BeZero())
})
Expand Down Expand Up @@ -154,4 +153,40 @@ var _ = Describe("Podman events", func() {

Expect(eventsMap).To(HaveKey("Status"))
})

It("podman events --until future", func() {
name1 := stringid.GenerateNonCryptoID()
name2 := stringid.GenerateNonCryptoID()
name3 := stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"create", "--name", name1, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

var wg sync.WaitGroup
wg.Add(1)
go func() {
defer GinkgoRecover()
defer wg.Done()

// wait 2 seconds to be sure events is running
time.Sleep(time.Second * 2)
session = podmanTest.Podman([]string{"create", "--name", name2, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"create", "--name", name3, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
}()

// unix timestamp in 10 seconds
until := time.Now().Add(time.Second * 10).Unix()
result := podmanTest.Podman([]string{"events", "--since", "30s", "--until", fmt.Sprint(until)})
result.Wait(11)
Expect(result.ExitCode()).To(BeZero())
Expect(result.OutputToString()).To(ContainSubstring(name1))
Expect(result.OutputToString()).To(ContainSubstring(name2))
Expect(result.OutputToString()).To(ContainSubstring(name3))

wg.Wait()
})
})

0 comments on commit 74fcd9f

Please sign in to comment.