Implemented Until Query Parameter for Containers/logs

compat containers/logs was missing actual usage of until query param.

fixes #10859

Signed-off-by: cdoern <cdoern@redhat.com>
This commit is contained in:
cdoern
2021-07-06 14:53:56 -04:00
parent 1a9cb93f16
commit 4624142c2d
5 changed files with 38 additions and 9 deletions

View File

@ -56,7 +56,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
for _, nll := range tailLog {
nll.CID = c.ID()
nll.CName = c.Name()
if nll.Since(options.Since) {
if nll.Since(options.Since) && nll.Until(options.Until) {
logChannel <- nll
}
}
@ -88,7 +88,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
}
nll.CID = c.ID()
nll.CName = c.Name()
if nll.Since(options.Since) {
if nll.Since(options.Since) && nll.Until(options.Until) {
logChannel <- nll
}
}

View File

@ -97,6 +97,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
}
}()
beforeTimeStamp := true
afterTimeStamp := false // needed for options.Since
tailQueue := []*logs.LogLine{} // needed for options.Tail
doTail := options.Tail > 0
@ -156,6 +157,13 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
}
afterTimeStamp = true
}
if beforeTimeStamp {
entryTime := time.Unix(0, int64(entry.RealtimeTimestamp)*int64(time.Microsecond))
if entryTime.Before(options.Until) || !options.Until.IsZero() {
continue
}
beforeTimeStamp = false
}
// If we're reading an event and the container exited/died,
// then we're done and can return.

View File

@ -34,6 +34,7 @@ type LogOptions struct {
Details bool
Follow bool
Since time.Time
Until time.Time
Tail int64
Timestamps bool
Multi bool
@ -184,7 +185,12 @@ func (l *LogLine) String(options *LogOptions) string {
// Since returns a bool as to whether a log line occurred after a given time
func (l *LogLine) Since(since time.Time) bool {
return l.Time.After(since)
return l.Time.After(since) || since.IsZero()
}
// Until returns a bool as to whether a log line occurred before a given time
func (l *LogLine) Until(until time.Time) bool {
return l.Time.Before(until) || until.IsZero()
}
// NewLogLine creates a logLine struct from a container log string

View File

@ -72,18 +72,20 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
var until time.Time
if _, found := r.URL.Query()["until"]; found {
// FIXME: until != since but the logs backend does not yet support until.
since, err = util.ParseInputTime(query.Until)
if query.Until != "0" {
until, err = util.ParseInputTime(query.Until)
if err != nil {
utils.BadRequest(w, "until", query.Until, err)
return
}
}
}
options := &logs.LogOptions{
Details: true,
Follow: query.Follow,
Since: since,
Until: until,
Tail: tail,
Timestamps: query.Timestamps,
}
@ -119,7 +121,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
for line := range logChannel {
if _, found := r.URL.Query()["until"]; found {
if line.Time.After(until) {
if line.Time.After(until) && !until.IsZero() {
break
}
}

View File

@ -1,5 +1,6 @@
import random
import unittest
import json
import requests
from dateutil.parser import parse
@ -97,6 +98,18 @@ class ContainerTestCase(APITestCase):
def test_logs(self):
r = requests.get(self.uri(self.resolve_container("/containers/{}/logs?stdout=true")))
self.assertEqual(r.status_code, 200, r.text)
r = requests.post(
self.podman_url + "/v1.40/containers/create?name=topcontainer",
json={"Cmd": ["top", "ls"], "Image": "alpine:latest"},
)
self.assertEqual(r.status_code, 201, r.text)
payload = r.json()
container_id = payload["Id"]
self.assertIsNotNone(container_id)
r = requests.get(self.podman_url + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=0")
self.assertEqual(r.status_code, 200, r.text)
r = requests.get(self.podman_url + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=1")
self.assertEqual(r.status_code, 200, r.text)
def test_commit(self):
r = requests.post(self.uri(self.resolve_container("/commit?container={}")))