summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/containers.go27
-rw-r--r--pkg/adapter/containers_remote.go47
-rw-r--r--pkg/inspect/inspect.go1
-rw-r--r--pkg/rootless/rootless_linux.go2
-rw-r--r--pkg/spec/createconfig.go2
-rw-r--r--pkg/util/utils.go57
-rw-r--r--pkg/varlinkapi/containers.go54
7 files changed, 156 insertions, 34 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 756369196..932d209cd 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -4,7 +4,9 @@ package adapter
import (
"context"
+ "fmt"
"strconv"
+ "sync"
"syscall"
"time"
@@ -127,3 +129,28 @@ func (r *LocalRuntime) WaitOnContainers(ctx context.Context, cli *cliconfig.Wait
}
return ok, failures, err
}
+
+// Log logs one or more containers
+func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions) error {
+ var wg sync.WaitGroup
+ options.WaitGroup = &wg
+ if len(c.InputArgs) > 1 {
+ options.Multi = true
+ }
+ logChannel := make(chan *libpod.LogLine, int(c.Tail)*len(c.InputArgs)+1)
+ containers, err := shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
+ if err != nil {
+ return err
+ }
+ if err := r.Runtime.Log(containers, options, logChannel); err != nil {
+ return err
+ }
+ go func() {
+ wg.Wait()
+ close(logChannel)
+ }()
+ for line := range logChannel {
+ fmt.Println(line.String(options))
+ }
+ return nil
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 5646d2297..a8146567a 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -5,18 +5,19 @@ package adapter
import (
"context"
"encoding/json"
- "errors"
+ "fmt"
"strconv"
"syscall"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
- "github.com/sirupsen/logrus"
-
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/inspect"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "github.com/varlink/go/varlink"
)
// Inspect returns an inspect struct from varlink
@@ -223,3 +224,41 @@ func BatchContainerOp(ctr *Container, opts shared.PsOptions) (shared.BatchContai
}
return bcs, nil
}
+
+// Logs one or more containers over a varlink connection
+func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions) error {
+ //GetContainersLogs
+ reply, err := iopodman.GetContainersLogs().Send(r.Conn, uint64(varlink.More), c.InputArgs, c.Follow, c.Latest, options.Since.Format(time.RFC3339Nano), int64(c.Tail), c.Timestamps)
+ if err != nil {
+ return errors.Wrapf(err, "failed to get container logs")
+ }
+ if len(c.InputArgs) > 1 {
+ options.Multi = true
+ }
+ for {
+ log, flags, err := reply()
+ if err != nil {
+ return err
+ }
+ if log.Time == "" && log.Msg == "" {
+ // We got a blank log line which can signal end of stream
+ break
+ }
+ lTime, err := time.Parse(time.RFC3339Nano, log.Time)
+ if err != nil {
+ return errors.Wrapf(err, "unable to parse time of log %s", log.Time)
+ }
+ logLine := libpod.LogLine{
+ Device: log.Device,
+ ParseLogType: log.ParseLogType,
+ Time: lTime,
+ Msg: log.Msg,
+ CID: log.Cid,
+ }
+ fmt.Println(logLine.String(options))
+ if flags&varlink.Continues == 0 {
+ break
+ }
+ }
+ return nil
+}
diff --git a/pkg/inspect/inspect.go b/pkg/inspect/inspect.go
index 82fe37f18..270e431ad 100644
--- a/pkg/inspect/inspect.go
+++ b/pkg/inspect/inspect.go
@@ -158,6 +158,7 @@ type ContainerInspectData struct {
HostsPath string `json:"HostsPath"`
StaticDir string `json:"StaticDir"`
LogPath string `json:"LogPath"`
+ ConmonPidFile string `json:"ConmonPidFile"`
Name string `json:"Name"`
RestartCount int32 `json:"RestartCount"` //TODO
Driver string `json:"Driver"`
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index b2677f7d9..baceebee3 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -72,7 +72,7 @@ func GetRootlessUID() int {
u, _ := strconv.Atoi(uidEnv)
return u
}
- return os.Getuid()
+ return os.Geteuid()
}
func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap) error {
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index a61c88d58..118fbad72 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -363,7 +363,7 @@ func (c *CreateConfig) createExitCommand() []string {
command = append(command, []string{"--storage-driver", config.StorageConfig.GraphDriverName}...)
}
if c.Syslog {
- command = append(command, "--syslog")
+ command = append(command, "--syslog", "true")
}
command = append(command, []string{"container", "cleanup"}...)
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index d7e1ddd38..a408ad34b 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -190,15 +190,15 @@ func GetRootlessRuntimeDir() (string, error) {
tmpDir := filepath.Join("/run", "user", uid)
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
- if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 {
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
- tmpDir := filepath.Join(os.TempDir(), "user", uid)
+ tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid))
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
- if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 {
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
@@ -311,36 +311,37 @@ func GetDefaultStoreOptions() (storage.StoreOptions, error) {
storageOpts = storage.StoreOptions{}
storage.ReloadConfigurationFile(storageConf, &storageOpts)
}
-
- if rootless.IsRootless() {
- if os.IsNotExist(err) {
- os.MkdirAll(filepath.Dir(storageConf), 0755)
- file, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
- if err != nil {
- return storageOpts, errors.Wrapf(err, "cannot open %s", storageConf)
- }
-
- tomlConfiguration := getTomlStorage(&storageOpts)
- defer file.Close()
- enc := toml.NewEncoder(file)
- if err := enc.Encode(tomlConfiguration); err != nil {
- os.Remove(storageConf)
- }
- } else if err == nil {
- // If the file did not specify a graphroot or runroot,
- // set sane defaults so we don't try and use root-owned
- // directories
- if storageOpts.RunRoot == "" {
- storageOpts.RunRoot = defaultRootlessRunRoot
- }
- if storageOpts.GraphRoot == "" {
- storageOpts.GraphRoot = defaultRootlessGraphRoot
- }
+ if rootless.IsRootless() && err == nil {
+ // If the file did not specify a graphroot or runroot,
+ // set sane defaults so we don't try and use root-owned
+ // directories
+ if storageOpts.RunRoot == "" {
+ storageOpts.RunRoot = defaultRootlessRunRoot
+ }
+ if storageOpts.GraphRoot == "" {
+ storageOpts.GraphRoot = defaultRootlessGraphRoot
}
}
return storageOpts, nil
}
+// WriteStorageConfigFile writes the configuration to a file
+func WriteStorageConfigFile(storageOpts *storage.StoreOptions, storageConf string) error {
+ os.MkdirAll(filepath.Dir(storageConf), 0755)
+ file, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
+ if err != nil {
+ return errors.Wrapf(err, "cannot open %s", storageConf)
+ }
+ tomlConfiguration := getTomlStorage(storageOpts)
+ defer file.Close()
+ enc := toml.NewEncoder(file)
+ if err := enc.Encode(tomlConfiguration); err != nil {
+ os.Remove(storageConf)
+ return err
+ }
+ return nil
+}
+
// StorageConfigFile returns the path to the storage config file used
func StorageConfigFile() string {
if rootless.IsRootless() {
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index fe38a7cdc..3185ba0e9 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -7,6 +7,7 @@ import (
"io"
"io/ioutil"
"os"
+ "sync"
"syscall"
"time"
@@ -602,3 +603,56 @@ func ContainerStatsToLibpodContainerStats(stats iopodman.ContainerStats) libpod.
}
return cstats
}
+
+// GetContainersLogs is the varlink endpoint to obtain one or more container logs
+func (i *LibpodAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
+ var wg sync.WaitGroup
+ if call.WantsMore() {
+ call.Continues = true
+ }
+ sinceTime, err := time.Parse(time.RFC3339Nano, since)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ options := libpod.LogOptions{
+ Follow: follow,
+ Since: sinceTime,
+ Tail: uint64(tail),
+ Timestamps: timestamps,
+ }
+
+ options.WaitGroup = &wg
+ if len(names) > 1 {
+ options.Multi = true
+ }
+ logChannel := make(chan *libpod.LogLine, int(tail)*len(names)+1)
+ containers, err := shortcuts.GetContainersByContext(false, latest, names, i.Runtime)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ if err := i.Runtime.Log(containers, &options, logChannel); err != nil {
+ return err
+ }
+ go func() {
+ wg.Wait()
+ close(logChannel)
+ }()
+ for line := range logChannel {
+ call.ReplyGetContainersLogs(newPodmanLogLine(line))
+ if !call.Continues {
+ break
+ }
+
+ }
+ return call.ReplyGetContainersLogs(iopodman.LogLine{})
+}
+
+func newPodmanLogLine(line *libpod.LogLine) iopodman.LogLine {
+ return iopodman.LogLine{
+ Device: line.Device,
+ ParseLogType: line.ParseLogType,
+ Time: line.Time.Format(time.RFC3339Nano),
+ Msg: line.Msg,
+ Cid: line.CID,
+ }
+}