mirror of
https://github.com/containers/podman.git
synced 2025-07-17 17:43:23 +08:00
Merge pull request #10868 from cdoern/untilLog
Implemented Until Query Parameter for Containers/logs
This commit is contained in:
@ -56,7 +56,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
|
|||||||
for _, nll := range tailLog {
|
for _, nll := range tailLog {
|
||||||
nll.CID = c.ID()
|
nll.CID = c.ID()
|
||||||
nll.CName = c.Name()
|
nll.CName = c.Name()
|
||||||
if nll.Since(options.Since) {
|
if nll.Since(options.Since) && nll.Until(options.Until) {
|
||||||
logChannel <- nll
|
logChannel <- nll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
|
|||||||
}
|
}
|
||||||
nll.CID = c.ID()
|
nll.CID = c.ID()
|
||||||
nll.CName = c.Name()
|
nll.CName = c.Name()
|
||||||
if nll.Since(options.Since) {
|
if nll.Since(options.Since) && nll.Until(options.Until) {
|
||||||
logChannel <- nll
|
logChannel <- nll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
beforeTimeStamp := true
|
||||||
afterTimeStamp := false // needed for options.Since
|
afterTimeStamp := false // needed for options.Since
|
||||||
tailQueue := []*logs.LogLine{} // needed for options.Tail
|
tailQueue := []*logs.LogLine{} // needed for options.Tail
|
||||||
doTail := options.Tail > 0
|
doTail := options.Tail > 0
|
||||||
@ -156,6 +157,13 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
|
|||||||
}
|
}
|
||||||
afterTimeStamp = true
|
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,
|
// If we're reading an event and the container exited/died,
|
||||||
// then we're done and can return.
|
// then we're done and can return.
|
||||||
|
@ -34,6 +34,7 @@ type LogOptions struct {
|
|||||||
Details bool
|
Details bool
|
||||||
Follow bool
|
Follow bool
|
||||||
Since time.Time
|
Since time.Time
|
||||||
|
Until time.Time
|
||||||
Tail int64
|
Tail int64
|
||||||
Timestamps bool
|
Timestamps bool
|
||||||
Multi 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
|
// Since returns a bool as to whether a log line occurred after a given time
|
||||||
func (l *LogLine) Since(since time.Time) bool {
|
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
|
// NewLogLine creates a logLine struct from a container log string
|
||||||
|
@ -72,11 +72,12 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var until time.Time
|
var until time.Time
|
||||||
if _, found := r.URL.Query()["until"]; found {
|
if _, found := r.URL.Query()["until"]; found {
|
||||||
// FIXME: until != since but the logs backend does not yet support until.
|
if query.Until != "0" {
|
||||||
since, err = util.ParseInputTime(query.Until)
|
until, err = util.ParseInputTime(query.Until)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.BadRequest(w, "until", query.Until, err)
|
utils.BadRequest(w, "until", query.Until, err)
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
Details: true,
|
Details: true,
|
||||||
Follow: query.Follow,
|
Follow: query.Follow,
|
||||||
Since: since,
|
Since: since,
|
||||||
|
Until: until,
|
||||||
Tail: tail,
|
Tail: tail,
|
||||||
Timestamps: query.Timestamps,
|
Timestamps: query.Timestamps,
|
||||||
}
|
}
|
||||||
@ -119,7 +121,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
for line := range logChannel {
|
for line := range logChannel {
|
||||||
if _, found := r.URL.Query()["until"]; found {
|
if _, found := r.URL.Query()["until"]; found {
|
||||||
if line.Time.After(until) {
|
if line.Time.After(until) && !until.IsZero() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import random
|
import random
|
||||||
import unittest
|
import unittest
|
||||||
|
import json
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from dateutil.parser import parse
|
from dateutil.parser import parse
|
||||||
@ -97,6 +98,18 @@ class ContainerTestCase(APITestCase):
|
|||||||
def test_logs(self):
|
def test_logs(self):
|
||||||
r = requests.get(self.uri(self.resolve_container("/containers/{}/logs?stdout=true")))
|
r = requests.get(self.uri(self.resolve_container("/containers/{}/logs?stdout=true")))
|
||||||
self.assertEqual(r.status_code, 200, r.text)
|
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):
|
def test_commit(self):
|
||||||
r = requests.post(self.uri(self.resolve_container("/commit?container={}")))
|
r = requests.post(self.uri(self.resolve_container("/commit?container={}")))
|
||||||
|
Reference in New Issue
Block a user