summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/common_test.go1
-rw-r--r--libpod/container.go8
-rw-r--r--libpod/container_internal.go33
-rw-r--r--libpod/image/filters.go9
-rw-r--r--libpod/logs/log.go88
-rw-r--r--libpod/logs/reversereader/reversereader.go66
-rw-r--r--libpod/options.go3
-rw-r--r--libpod/runtime_pod_infra_linux.go2
-rw-r--r--libpod/util_test.go3
9 files changed, 177 insertions, 36 deletions
diff --git a/libpod/common_test.go b/libpod/common_test.go
index 83b162c8a..63ea4f41b 100644
--- a/libpod/common_test.go
+++ b/libpod/common_test.go
@@ -23,7 +23,6 @@ func getTestContainer(id, name string, manager lock.Manager) (*Container, error)
Name: name,
RootfsImageID: id,
RootfsImageName: "testimg",
- ImageVolumes: true,
StaticDir: "/does/not/exist/",
LogPath: "/does/not/exist/",
Stdin: true,
diff --git a/libpod/container.go b/libpod/container.go
index 5e5c8ab26..dbd15e55f 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -249,8 +249,6 @@ type ContainerConfig struct {
RootfsImageName string `json:"rootfsImageName,omitempty"`
// Rootfs to use for the container, this conflicts with RootfsImageID
Rootfs string `json:"rootfs,omitempty"`
- // Whether to mount volumes specified in the image.
- ImageVolumes bool `json:"imageVolumes"`
// Src path to be mounted on /dev/shm in container.
ShmDir string `json:"ShmDir,omitempty"`
// Size of the container's SHM.
@@ -510,12 +508,6 @@ func (c *Container) Image() (string, string) {
return c.config.RootfsImageID, c.config.RootfsImageName
}
-// ImageVolumes returns whether the container is configured to create
-// persistent volumes requested by the image
-func (c *Container) ImageVolumes() bool {
- return c.config.ImageVolumes
-}
-
// ShmDir returns the sources path to be mounted on /dev/shm in container
func (c *Container) ShmDir() string {
return c.config.ShmDir
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 216bbe669..11f9721dc 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -914,6 +914,7 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
}
func (c *Container) completeNetworkSetup() error {
+ var outResolvConf []string
netDisabled, err := c.NetworkDisabled()
if err != nil {
return err
@@ -927,7 +928,37 @@ func (c *Container) completeNetworkSetup() error {
if c.config.NetMode == "slirp4netns" {
return c.runtime.setupRootlessNetNS(c)
}
- return c.runtime.setupNetNS(c)
+ if err := c.runtime.setupNetNS(c); err != nil {
+ return err
+ }
+ state := c.state
+ // collect any dns servers that cni tells us to use (dnsname)
+ for _, cni := range state.NetworkStatus {
+ if cni.DNS.Nameservers != nil {
+ for _, server := range cni.DNS.Nameservers {
+ outResolvConf = append(outResolvConf, fmt.Sprintf("nameserver %s", server))
+ }
+ }
+ }
+ // check if we have a bindmount for resolv.conf
+ resolvBindMount := state.BindMounts["/etc/resolv.conf"]
+ if len(outResolvConf) < 1 || resolvBindMount == "" || len(c.config.NetNsCtr) > 0 {
+ return nil
+ }
+ // read the existing resolv.conf
+ b, err := ioutil.ReadFile(resolvBindMount)
+ if err != nil {
+ return err
+ }
+ for _, line := range strings.Split(string(b), "\n") {
+ // only keep things that dont start with nameserver from the old
+ // resolv.conf file
+ if !strings.HasPrefix(line, "nameserver") {
+ outResolvConf = append([]string{line}, outResolvConf...)
+ }
+ }
+ // write and return
+ return ioutil.WriteFile(resolvBindMount, []byte(strings.Join(outResolvConf, "\n")), 0644)
}
// Initialize a container, creating it in the runtime
diff --git a/libpod/image/filters.go b/libpod/image/filters.go
index 7c7394930..c54ca6333 100644
--- a/libpod/image/filters.go
+++ b/libpod/image/filters.go
@@ -102,6 +102,13 @@ func ReferenceFilter(ctx context.Context, referenceFilter string) ResultFilter {
}
}
+// IdFilter allows you to filter by image Id
+func IdFilter(idFilter string) ResultFilter {
+ return func(i *Image) bool {
+ return i.ID() == idFilter
+ }
+}
+
// OutputImageFilter allows you to filter by an a specific image name
func OutputImageFilter(userImage *Image) ResultFilter {
return func(i *Image) bool {
@@ -165,6 +172,8 @@ func (ir *Runtime) createFilterFuncs(filters []string, img *Image) ([]ResultFilt
case "reference":
referenceFilter := strings.Join(splitFilter[1:], "=")
filterFuncs = append(filterFuncs, ReferenceFilter(ctx, referenceFilter))
+ case "id":
+ filterFuncs = append(filterFuncs, IdFilter(splitFilter[1]))
default:
return nil, errors.Errorf("invalid filter %s ", splitFilter[0])
}
diff --git a/libpod/logs/log.go b/libpod/logs/log.go
index 9a7bcb5be..bd918abae 100644
--- a/libpod/logs/log.go
+++ b/libpod/logs/log.go
@@ -2,13 +2,16 @@ package logs
import (
"fmt"
- "io/ioutil"
+ "io"
+ "os"
"strings"
"sync"
"time"
+ "github.com/containers/libpod/libpod/logs/reversereader"
"github.com/hpcloud/tail"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
const (
@@ -74,43 +77,84 @@ func GetLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error
func getTailLog(path string, tail int) ([]*LogLine, error) {
var (
- tailLog []*LogLine
- nlls []*LogLine
- tailCounter int
- partial string
+ nlls []*LogLine
+ nllCounter int
+ leftover string
+ partial string
+ tailLog []*LogLine
)
- content, err := ioutil.ReadFile(path)
+ f, err := os.Open(path)
if err != nil {
return nil, err
}
- splitContent := strings.Split(string(content), "\n")
- // We read the content in reverse and add each nll until we have the same
- // number of F type messages as the desired tail
- for i := len(splitContent) - 1; i >= 0; i-- {
- if len(splitContent[i]) == 0 {
- continue
- }
- nll, err := NewLogLine(splitContent[i])
- if err != nil {
- return nil, err
+ rr, err := reversereader.NewReverseReader(f)
+ if err != nil {
+ return nil, err
+ }
+
+ inputs := make(chan []string)
+ go func() {
+ for {
+ s, err := rr.Read()
+ if err != nil {
+ if errors.Cause(err) == io.EOF {
+ inputs <- []string{leftover}
+ close(inputs)
+ break
+ }
+ logrus.Error(err)
+ close(inputs)
+ }
+ line := strings.Split(s+leftover, "\n")
+ if len(line) > 1 {
+ inputs <- line[1:]
+ }
+ leftover = line[0]
}
- nlls = append(nlls, nll)
- if !nll.Partial() {
- tailCounter++
+ }()
+
+ for i := range inputs {
+ // the incoming array is FIFO; we want FIFO so
+ // reverse the slice read order
+ for j := len(i) - 1; j >= 0; j-- {
+ // lines that are "" are junk
+ if len(i[j]) < 1 {
+ continue
+ }
+ // read the content in reverse and add each nll until we have the same
+ // number of F type messages as the desired tail
+ nll, err := NewLogLine(i[j])
+ if err != nil {
+ return nil, err
+ }
+ nlls = append(nlls, nll)
+ if !nll.Partial() {
+ nllCounter++
+ }
}
- if tailCounter == tail {
+ // if we have enough loglines, we can hangup
+ if nllCounter >= tail {
+ if err := f.Close(); err != nil {
+ logrus.Error(err)
+ }
break
}
}
- // Now we iterate the results and assemble partial messages to become full messages
+
+ // re-assemble the log lines and trim (if needed) to the
+ // tail length
for _, nll := range nlls {
if nll.Partial() {
partial += nll.Msg
} else {
nll.Msg += partial
- tailLog = append(tailLog, nll)
+ // prepend because we need to reverse the order again to FIFO
+ tailLog = append([]*LogLine{nll}, tailLog...)
partial = ""
}
+ if len(tailLog) == tail {
+ break
+ }
}
return tailLog, nil
}
diff --git a/libpod/logs/reversereader/reversereader.go b/libpod/logs/reversereader/reversereader.go
new file mode 100644
index 000000000..72d9ad975
--- /dev/null
+++ b/libpod/logs/reversereader/reversereader.go
@@ -0,0 +1,66 @@
+package reversereader
+
+import (
+ "io"
+ "os"
+
+ "github.com/pkg/errors"
+)
+
+// ReverseReader structure for reading a file backwards
+type ReverseReader struct {
+ reader *os.File
+ offset int64
+ readSize int64
+}
+
+// NewReverseReader returns a reader that reads from the end of a file
+// rather than the beginning. It sets the readsize to pagesize and determines
+// the first offset using using modulus.
+func NewReverseReader(reader *os.File) (*ReverseReader, error) {
+ // pagesize should be safe for memory use and file reads should be on page
+ // boundaries as well
+ pageSize := int64(os.Getpagesize())
+ stat, err := reader.Stat()
+ if err != nil {
+ return nil, err
+ }
+ // figure out the last page boundary
+ remainder := stat.Size() % pageSize
+ end, err := reader.Seek(0, 2)
+ if err != nil {
+ return nil, err
+ }
+ // set offset (starting position) to the last page boundary or
+ // zero if fits in one page
+ startOffset := end - remainder
+ if startOffset < 0 {
+ startOffset = 0
+ }
+ rr := ReverseReader{
+ reader: reader,
+ offset: startOffset,
+ readSize: pageSize,
+ }
+ return &rr, nil
+}
+
+// ReverseReader reads from a given offset to the previous offset and
+// then sets the newoff set one pagesize less than the previous read.
+func (r *ReverseReader) Read() (string, error) {
+ if r.offset < 0 {
+ return "", errors.Wrap(io.EOF, "at beginning of file")
+ }
+ // Read from given offset
+ b := make([]byte, r.readSize)
+ n, err := r.reader.ReadAt(b, r.offset)
+ if err != nil && errors.Cause(err) != io.EOF {
+ return "", err
+ }
+ if int64(n) < r.readSize {
+ b = b[0:n]
+ }
+ // Set to the next page boundary
+ r.offset = -r.readSize
+ return string(b), nil
+}
diff --git a/libpod/options.go b/libpod/options.go
index 1fd588867..d01e8a85f 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -593,7 +593,7 @@ func WithUser(user string) CtrCreateOption {
// other configuration from the image will be added to the config.
// TODO: Replace image name and ID with a libpod.Image struct when that is
// finished.
-func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool) CtrCreateOption {
+func WithRootFSFromImage(imageID string, imageName string) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return define.ErrCtrFinalized
@@ -608,7 +608,6 @@ func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool)
ctr.config.RootfsImageID = imageID
ctr.config.RootfsImageName = imageName
- ctr.config.ImageVolumes = useImageVolumes
return nil
}
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index a6cac2b72..da46f03e8 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -127,7 +127,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
containerName := p.ID()[:IDTruncLength] + "-infra"
options = append(options, r.WithPod(p))
- options = append(options, WithRootFSFromImage(imgID, imgName, false))
+ options = append(options, WithRootFSFromImage(imgID, imgName))
options = append(options, WithName(containerName))
options = append(options, withIsInfra())
diff --git a/libpod/util_test.go b/libpod/util_test.go
index 70e989e1a..227686c2b 100644
--- a/libpod/util_test.go
+++ b/libpod/util_test.go
@@ -1,8 +1,9 @@
package libpod
import (
- "github.com/stretchr/testify/assert"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func TestRemoveScientificNotationFromFloat(t *testing.T) {