diff options
-rw-r--r-- | libpod/container_log.go | 4 | ||||
-rw-r--r-- | libpod/container_log_linux.go | 8 | ||||
-rw-r--r-- | libpod/logs/log.go | 8 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_logs.go | 14 | ||||
-rw-r--r-- | pkg/bindings/images/build.go | 6 | ||||
-rw-r--r-- | test/apiv2/python/rest_api/test_v2_0_0_container.py | 13 | ||||
-rw-r--r-- | test/system/070-build.bats | 34 |
7 files changed, 76 insertions, 11 deletions
diff --git a/libpod/container_log.go b/libpod/container_log.go index 43b3f7736..743c9c61b 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -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 } } diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go index 892ee34e3..9f9dd3b0d 100644 --- a/libpod/container_log_linux.go +++ b/libpod/container_log_linux.go @@ -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. diff --git a/libpod/logs/log.go b/libpod/logs/log.go index 308053b47..1a0223edc 100644 --- a/libpod/logs/log.go +++ b/libpod/logs/log.go @@ -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 diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go index cb4dee4d2..656e2c627 100644 --- a/pkg/api/handlers/compat/containers_logs.go +++ b/pkg/api/handlers/compat/containers_logs.go @@ -72,11 +72,12 @@ 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 err != nil { - utils.BadRequest(w, "until", query.Until, err) - return + if query.Until != "0" { + until, err = util.ParseInputTime(query.Until) + if err != nil { + utils.BadRequest(w, "until", query.Until, err) + return + } } } @@ -84,6 +85,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { 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 } } diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 95d9d4df7..3fbc41f99 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -301,6 +301,8 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO tarContent := []string{options.ContextDirectory} newContainerFiles := []string{} + + dontexcludes := []string{"!Dockerfile", "!Containerfile"} for _, c := range containerFiles { if c == "/dev/stdin" { content, err := ioutil.ReadAll(os.Stdin) @@ -328,6 +330,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO // Do NOT add to tarfile if strings.HasPrefix(containerfile, contextDir+string(filepath.Separator)) { containerfile = strings.TrimPrefix(containerfile, contextDir+string(filepath.Separator)) + dontexcludes = append(dontexcludes, "!"+containerfile) } else { // If Containerfile does not exists assume it is in context directory, do Not add to tarfile if _, err := os.Lstat(containerfile); err != nil { @@ -349,8 +352,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } params.Set("dockerfile", string(cFileJSON)) } - - tarfile, err := nTar(excludes, tarContent...) + tarfile, err := nTar(append(excludes, dontexcludes...), tarContent...) if err != nil { logrus.Errorf("cannot tar container entries %v error: %v", tarContent, err) return nil, err diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py index 2fab4aeb9..f252bd401 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_container.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py @@ -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={}"))) diff --git a/test/system/070-build.bats b/test/system/070-build.bats index c45a661fe..7046625c6 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -509,6 +509,40 @@ EOF done } +# Regression test for #9867 +# Make sure that if you exclude everything in context dir, that +# the Containerfile/Dockerfile in the context dir are used +@test "podman build with ignore '*'" { + local tmpdir=$PODMAN_TMPDIR/build-test-$(random_string 10) + mkdir -p $tmpdir + + cat >$tmpdir/Containerfile <<EOF +FROM scratch +EOF + +cat >$tmpdir/.dockerignore <<EOF +* +EOF + + run_podman build -t build_test $tmpdir + + # Rename Containerfile to Dockerfile + mv $tmpdir/Containerfile $tmpdir/Dockerfile + + run_podman build -t build_test $tmpdir + + # Rename Dockerfile to foofile + mv $tmpdir/Dockerfile $tmpdir/foofile + + run_podman 125 build -t build_test $tmpdir + is "$output" ".*Dockerfile: no such file or directory" + + run_podman build -t build_test -f $tmpdir/foofile $tmpdir + + # Clean up + run_podman rmi -f build_test +} + @test "podman build - stdin test" { # Random workdir, and random string to verify build output workdir=/$(random_string 10) |