summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_api.go2
-rw-r--r--libpod/container_log.go23
-rw-r--r--libpod/container_log_linux.go16
-rw-r--r--libpod/container_log_unsupported.go4
-rw-r--r--libpod/image/image.go6
-rw-r--r--libpod/runtime_img.go64
6 files changed, 82 insertions, 33 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go
index b37b05ff2..c7df9d66c 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -353,7 +353,7 @@ func (c *Container) HTTPAttach(httpCon net.Conn, httpBuf *bufio.ReadWriter, stre
logOpts.WaitGroup.Wait()
close(logChan)
}()
- if err := c.ReadLog(logOpts, logChan); err != nil {
+ if err := c.ReadLog(context.Background(), logOpts, logChan); err != nil {
return err
}
logrus.Debugf("Done reading logs for container %s, %d bytes", c.ID(), logSize)
diff --git a/libpod/container_log.go b/libpod/container_log.go
index 97936c683..80f8e6e50 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "context"
"fmt"
"os"
"time"
@@ -13,9 +14,9 @@ import (
)
// Log is a runtime function that can read one or more container logs.
-func (r *Runtime) Log(containers []*Container, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+func (r *Runtime) Log(ctx context.Context, containers []*Container, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
for _, ctr := range containers {
- if err := ctr.ReadLog(options, logChannel); err != nil {
+ if err := ctr.ReadLog(ctx, options, logChannel); err != nil {
return err
}
}
@@ -23,25 +24,25 @@ func (r *Runtime) Log(containers []*Container, options *logs.LogOptions, logChan
}
// ReadLog reads a containers log based on the input options and returns loglines over a channel.
-func (c *Container) ReadLog(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+func (c *Container) ReadLog(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
switch c.LogDriver() {
case define.NoLogging:
return errors.Wrapf(define.ErrNoLogs, "this container is using the 'none' log driver, cannot read logs")
case define.JournaldLogging:
// TODO Skip sending logs until journald logs can be read
- return c.readFromJournal(options, logChannel)
+ return c.readFromJournal(ctx, options, logChannel)
case define.JSONLogging:
// TODO provide a separate implementation of this when Conmon
// has support.
fallthrough
case define.KubernetesLogging, "":
- return c.readFromLogFile(options, logChannel)
+ return c.readFromLogFile(ctx, options, logChannel)
default:
return errors.Wrapf(define.ErrInternal, "unrecognized log driver %q, cannot read logs", c.LogDriver())
}
}
-func (c *Container) readFromLogFile(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
t, tailLog, err := logs.GetLogFile(c.LogPath(), options)
if err != nil {
// If the log file does not exist, this is not fatal.
@@ -62,8 +63,17 @@ func (c *Container) readFromLogFile(options *logs.LogOptions, logChannel chan *l
}
go func() {
+ defer options.WaitGroup.Done()
+
var partial string
for line := range t.Lines {
+ select {
+ case <-ctx.Done():
+ // the consumer has cancelled
+ return
+ default:
+ // fallthrough
+ }
nll, err := logs.NewLogLine(line.Text)
if err != nil {
logrus.Error(err)
@@ -82,7 +92,6 @@ func (c *Container) readFromLogFile(options *logs.LogOptions, logChannel chan *l
logChannel <- nll
}
}
- options.WaitGroup.Done()
}()
// Check if container is still running or paused
if options.Follow {
diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go
index fad3bf87c..00b2039a9 100644
--- a/libpod/container_log_linux.go
+++ b/libpod/container_log_linux.go
@@ -4,6 +4,7 @@
package libpod
import (
+ "context"
"fmt"
"io"
"math"
@@ -29,7 +30,7 @@ const (
bufLen = 16384
)
-func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
var config journal.JournalReaderConfig
if options.Tail < 0 {
config.NumFromTail = math.MaxUint64
@@ -65,13 +66,24 @@ func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *l
if options.Follow {
go func() {
+ done := make(chan bool)
+ until := make(chan time.Time)
+ go func() {
+ select {
+ case <-ctx.Done():
+ until <- time.Time{}
+ case <-done:
+ // nothing to do anymore
+ }
+ }()
follower := FollowBuffer{logChannel}
- err := r.Follow(nil, follower)
+ err := r.Follow(until, follower)
if err != nil {
logrus.Debugf(err.Error())
}
r.Close()
options.WaitGroup.Done()
+ done <- true
return
}()
return nil
diff --git a/libpod/container_log_unsupported.go b/libpod/container_log_unsupported.go
index 18882720a..f3b36619e 100644
--- a/libpod/container_log_unsupported.go
+++ b/libpod/container_log_unsupported.go
@@ -3,11 +3,13 @@
package libpod
import (
+ "context"
+
"github.com/containers/libpod/v2/libpod/define"
"github.com/containers/libpod/v2/libpod/logs"
"github.com/pkg/errors"
)
-func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *logs.LogLine) error {
+func (c *Container) readFromJournal(_ context.Context, _ *logs.LogOptions, _ chan *logs.LogLine) error {
return errors.Wrapf(define.ErrOSNotSupported, "Journald logging only enabled with systemd on linux")
}
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 048ec825d..e2bd1ad5d 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -21,6 +21,7 @@ import (
"github.com/containers/image/v5/image"
"github.com/containers/image/v5/manifest"
ociarchive "github.com/containers/image/v5/oci/archive"
+ "github.com/containers/image/v5/oci/layout"
is "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/tarball"
"github.com/containers/image/v5/transports"
@@ -1483,9 +1484,10 @@ func (i *Image) Save(ctx context.Context, source, format, output string, moreTag
return errors.Wrapf(err, "error getting OCI archive ImageReference for (%q, %q)", output, destImageName)
}
case "oci-dir":
- destRef, err = directory.NewReference(output)
+ destImageName := imageNameForSaveDestination(i, source)
+ destRef, err = layout.NewReference(output, destImageName) // destImageName may be ""
if err != nil {
- return errors.Wrapf(err, "error getting directory ImageReference for %q", output)
+ return errors.Wrapf(err, "error getting the OCI directory ImageReference for (%q, %q)", output, destImageName)
}
manifestType = imgspecv1.MediaTypeImageManifest
case "docker-dir":
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index eab05f34d..370c9d610 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -8,9 +8,15 @@ import (
"net/http"
"net/url"
"os"
+ "strings"
"github.com/containers/buildah/imagebuildah"
+ "github.com/containers/image/v5/directory"
"github.com/containers/image/v5/docker/reference"
+ ociarchive "github.com/containers/image/v5/oci/archive"
+ "github.com/containers/image/v5/oci/layout"
+ "github.com/containers/image/v5/types"
+
"github.com/containers/libpod/v2/libpod/define"
"github.com/containers/libpod/v2/libpod/image"
"github.com/containers/libpod/v2/pkg/util"
@@ -18,9 +24,7 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
- "github.com/containers/image/v5/directory"
dockerarchive "github.com/containers/image/v5/docker/archive"
- ociarchive "github.com/containers/image/v5/oci/archive"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
@@ -256,28 +260,48 @@ func DownloadFromFile(reader *os.File) (string, error) {
// LoadImage loads a container image into local storage
func (r *Runtime) LoadImage(ctx context.Context, name, inputFile string, writer io.Writer, signaturePolicy string) (string, error) {
- var newImages []*image.Image
- src, err := dockerarchive.ParseReference(inputFile) // FIXME? We should add dockerarchive.NewReference()
- if err == nil {
- newImages, err = r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer)
- }
- if err != nil {
- // generate full src name with specified image:tag
- src, err := ociarchive.NewReference(inputFile, name) // imageName may be ""
- if err == nil {
- newImages, err = r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer)
- }
- if err != nil {
- src, err := directory.NewReference(inputFile)
- if err == nil {
- newImages, err = r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer)
+ var (
+ newImages []*image.Image
+ err error
+ src types.ImageReference
+ )
+
+ for _, referenceFn := range []func() (types.ImageReference, error){
+ func() (types.ImageReference, error) {
+ return dockerarchive.ParseReference(inputFile) // FIXME? We should add dockerarchive.NewReference()
+ },
+ func() (types.ImageReference, error) {
+ return ociarchive.NewReference(inputFile, name) // name may be ""
+ },
+ func() (types.ImageReference, error) {
+ // prepend "localhost/" to support local image saved with this semantics
+ if !strings.Contains(name, "/") {
+ return ociarchive.NewReference(inputFile, fmt.Sprintf("%s/%s", image.DefaultLocalRegistry, name))
+ }
+ return nil, nil
+ },
+ func() (types.ImageReference, error) {
+ return directory.NewReference(inputFile)
+ },
+ func() (types.ImageReference, error) {
+ return layout.NewReference(inputFile, name)
+ },
+ func() (types.ImageReference, error) {
+ // prepend "localhost/" to support local image saved with this semantics
+ if !strings.Contains(name, "/") {
+ return layout.NewReference(inputFile, fmt.Sprintf("%s/%s", image.DefaultLocalRegistry, name))
}
- if err != nil {
- return "", errors.Wrapf(err, "error pulling %q", name)
+ return nil, nil
+ },
+ } {
+ src, err = referenceFn()
+ if err == nil && src != nil {
+ if newImages, err = r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer); err == nil {
+ return getImageNames(newImages), nil
}
}
}
- return getImageNames(newImages), nil
+ return "", errors.Wrapf(err, "error pulling %q", name)
}
func getImageNames(images []*image.Image) string {