mirror of
https://github.com/containers/podman.git
synced 2025-08-06 19:44:14 +08:00
Merge pull request #6332 from jwhonce/jira/884
V2 enable remote logs and testing
This commit is contained in:
@ -29,6 +29,17 @@ var (
|
|||||||
Use: "logs [flags] CONTAINER [CONTAINER...]",
|
Use: "logs [flags] CONTAINER [CONTAINER...]",
|
||||||
Short: "Fetch the logs of one or more containers",
|
Short: "Fetch the logs of one or more containers",
|
||||||
Long: logsDescription,
|
Long: logsDescription,
|
||||||
|
Args: func(cmd *cobra.Command, args []string) error {
|
||||||
|
switch {
|
||||||
|
case registry.IsRemote() && len(args) > 1:
|
||||||
|
return errors.New(cmd.Name() + " does not support multiple containers when run remotely")
|
||||||
|
case logsOptions.Latest && len(args) > 0:
|
||||||
|
return errors.New("no containers can be specified when using 'latest'")
|
||||||
|
case !logsOptions.Latest && len(args) < 1:
|
||||||
|
return errors.New("specify at least one container name or ID to log")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
RunE: logs,
|
RunE: logs,
|
||||||
Example: `podman logs ctrID
|
Example: `podman logs ctrID
|
||||||
podman logs --names ctrID1 ctrID2
|
podman logs --names ctrID1 ctrID2
|
||||||
@ -41,6 +52,7 @@ var (
|
|||||||
Use: logsCommand.Use,
|
Use: logsCommand.Use,
|
||||||
Short: logsCommand.Short,
|
Short: logsCommand.Short,
|
||||||
Long: logsCommand.Long,
|
Long: logsCommand.Long,
|
||||||
|
Args: logsCommand.Args,
|
||||||
RunE: logsCommand.RunE,
|
RunE: logsCommand.RunE,
|
||||||
Example: `podman container logs ctrID
|
Example: `podman container logs ctrID
|
||||||
podman container logs --names ctrID1 ctrID2
|
podman container logs --names ctrID1 ctrID2
|
||||||
@ -53,7 +65,7 @@ var (
|
|||||||
func init() {
|
func init() {
|
||||||
// logs
|
// logs
|
||||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||||
Mode: []entities.EngineMode{entities.ABIMode},
|
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||||
Command: logsCommand,
|
Command: logsCommand,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -62,7 +74,7 @@ func init() {
|
|||||||
|
|
||||||
// container logs
|
// container logs
|
||||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||||
Mode: []entities.EngineMode{entities.ABIMode},
|
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||||
Command: containerLogsCommand,
|
Command: containerLogsCommand,
|
||||||
Parent: containerCmd,
|
Parent: containerCmd,
|
||||||
})
|
})
|
||||||
@ -84,12 +96,6 @@ func logsFlags(flags *pflag.FlagSet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func logs(cmd *cobra.Command, args []string) error {
|
func logs(cmd *cobra.Command, args []string) error {
|
||||||
if len(args) > 0 && logsOptions.Latest {
|
|
||||||
return errors.New("no containers can be specified when using 'latest'")
|
|
||||||
}
|
|
||||||
if !logsOptions.Latest && len(args) < 1 {
|
|
||||||
return errors.New("specify at least one container name or ID to log")
|
|
||||||
}
|
|
||||||
if logsOptions.SinceRaw != "" {
|
if logsOptions.SinceRaw != "" {
|
||||||
// parse time, error out if something is wrong
|
// parse time, error out if something is wrong
|
||||||
since, err := util.ParseInputTime(logsOptions.SinceRaw)
|
since, err := util.ParseInputTime(logsOptions.SinceRaw)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -295,7 +296,9 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
var builder strings.Builder
|
|
||||||
|
var frame strings.Builder
|
||||||
|
header := make([]byte, 8)
|
||||||
for ok := true; ok; ok = query.Follow {
|
for ok := true; ok; ok = query.Follow {
|
||||||
for line := range logChannel {
|
for line := range logChannel {
|
||||||
if _, found := r.URL.Query()["until"]; found {
|
if _, found := r.URL.Query()["until"]; found {
|
||||||
@ -304,10 +307,8 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset variables we're ready to loop again
|
// Reset buffer we're ready to loop again
|
||||||
builder.Reset()
|
frame.Reset()
|
||||||
header := [8]byte{}
|
|
||||||
|
|
||||||
switch line.Device {
|
switch line.Device {
|
||||||
case "stdout":
|
case "stdout":
|
||||||
if !query.Stdout {
|
if !query.Stdout {
|
||||||
@ -327,17 +328,17 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if query.Timestamps {
|
if query.Timestamps {
|
||||||
builder.WriteString(line.Time.Format(time.RFC3339))
|
frame.WriteString(line.Time.Format(time.RFC3339))
|
||||||
builder.WriteRune(' ')
|
frame.WriteString(" ")
|
||||||
}
|
}
|
||||||
builder.WriteString(line.Msg)
|
frame.WriteString(line.Msg)
|
||||||
// Build header and output entry
|
|
||||||
binary.BigEndian.PutUint32(header[4:], uint32(len(header)+builder.Len()))
|
binary.BigEndian.PutUint32(header[4:], uint32(frame.Len()))
|
||||||
if _, err := w.Write(header[:]); err != nil {
|
if _, err := w.Write(header[0:8]); err != nil {
|
||||||
log.Errorf("unable to write log output header: %q", err)
|
log.Errorf("unable to write log output header: %q", err)
|
||||||
}
|
}
|
||||||
if _, err := fmt.Fprint(w, builder.String()); err != nil {
|
if _, err := io.WriteString(w, frame.String()); err != nil {
|
||||||
log.Errorf("unable to write builder string: %q", err)
|
log.Errorf("unable to write frame string: %q", err)
|
||||||
}
|
}
|
||||||
if flusher, ok := w.(http.Flusher); ok {
|
if flusher, ok := w.(http.Flusher); ok {
|
||||||
flusher.Flush()
|
flusher.Flush()
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrLostSync = errors.New("lost synchronization with attach multiplexed result")
|
ErrLostSync = errors.New("lost synchronization with multiplexed stream")
|
||||||
)
|
)
|
||||||
|
|
||||||
// List obtains a list of containers in local storage. All parameters to this method are optional.
|
// List obtains a list of containers in local storage. All parameters to this method are optional.
|
||||||
@ -485,7 +485,7 @@ func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stre
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case fd == 3:
|
case fd == 3:
|
||||||
return fmt.Errorf("error from daemon in stream: %s", frame)
|
return errors.New("error from service in stream: " + string(frame))
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unrecognized input header: %d", fd)
|
return fmt.Errorf("unrecognized input header: %d", fd)
|
||||||
}
|
}
|
||||||
@ -507,7 +507,7 @@ func DemuxHeader(r io.Reader, buffer []byte) (fd, sz int, err error) {
|
|||||||
|
|
||||||
fd = int(buffer[0])
|
fd = int(buffer[0])
|
||||||
if fd < 0 || fd > 3 {
|
if fd < 0 || fd > 3 {
|
||||||
err = ErrLostSync
|
err = errors.Wrapf(ErrLostSync, fmt.Sprintf(`channel "%d" found, 0-3 supported`, fd))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,7 +528,6 @@ func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error
|
|||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer[0:length], nil
|
return buffer[0:length], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package containers
|
package containers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -49,68 +50,34 @@ func Logs(ctx context.Context, nameOrID string, opts LogOptions, stdoutChan, std
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
// read 8 bytes
|
buffer := make([]byte, 1024)
|
||||||
// first byte determines stderr=2|stdout=1
|
|
||||||
// bytes 4-7 len(msg) in uint32
|
|
||||||
for {
|
for {
|
||||||
stream, msgSize, err := readHeader(response.Body)
|
fd, l, err := DemuxHeader(response.Body, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// In case the server side closes up shop because !follow
|
if errors.Is(err, io.EOF) {
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return errors.Wrap(err, "unable to read log header")
|
|
||||||
}
|
|
||||||
msg, err := readMsg(response.Body, msgSize)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "unable to read log message")
|
|
||||||
}
|
|
||||||
if stream == 1 {
|
|
||||||
stdoutChan <- msg
|
|
||||||
} else {
|
|
||||||
stderrChan <- msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
func readMsg(r io.Reader, msgSize int) (string, error) {
|
}
|
||||||
var msg []byte
|
frame, err := DemuxFrame(response.Body, buffer, l)
|
||||||
size := msgSize
|
|
||||||
for {
|
|
||||||
b := make([]byte, size)
|
|
||||||
_, err := r.Read(b)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
msg = append(msg, b...)
|
frame = bytes.Replace(frame[0:l], []byte{13}, []byte{10}, -1)
|
||||||
if len(msg) == msgSize {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
size = msgSize - len(msg)
|
|
||||||
}
|
|
||||||
return string(msg), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func readHeader(r io.Reader) (byte, int, error) {
|
switch fd {
|
||||||
var (
|
case 0:
|
||||||
header []byte
|
stdoutChan <- string(frame)
|
||||||
size = 8
|
case 1:
|
||||||
)
|
stdoutChan <- string(frame)
|
||||||
for {
|
case 2:
|
||||||
b := make([]byte, size)
|
stderrChan <- string(frame)
|
||||||
_, err := r.Read(b)
|
case 3:
|
||||||
if err != nil {
|
return errors.New("error from service in stream: " + string(frame))
|
||||||
return 0, 0, err
|
default:
|
||||||
|
return fmt.Errorf("unrecognized input header: %d", fd)
|
||||||
}
|
}
|
||||||
header = append(header, b...)
|
|
||||||
if len(header) == 8 {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
size = 8 - len(header)
|
|
||||||
}
|
|
||||||
stream := header[0]
|
|
||||||
msgSize := int(binary.BigEndian.Uint32(header[4:]) - 8)
|
|
||||||
return stream, msgSize, nil
|
|
||||||
}
|
}
|
||||||
|
@ -378,9 +378,9 @@ var _ = Describe("Podman containers ", func() {
|
|||||||
containers.Logs(bt.conn, r.ID, opts, stdoutChan, nil)
|
containers.Logs(bt.conn, r.ID, opts, stdoutChan, nil)
|
||||||
}()
|
}()
|
||||||
o := <-stdoutChan
|
o := <-stdoutChan
|
||||||
o = strings.ReplaceAll(o, "\r", "")
|
o = strings.TrimSpace(o)
|
||||||
_, err = time.Parse(time.RFC1123Z, o)
|
_, err = time.Parse(time.RFC1123Z, o)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman top", func() {
|
It("podman top", func() {
|
||||||
|
@ -4,7 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
"github.com/containers/image/v5/docker/reference"
|
"github.com/containers/image/v5/docker/reference"
|
||||||
@ -336,9 +338,36 @@ func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecG
|
|||||||
return &entities.ContainerCreateReport{Id: response.ID}, nil
|
return &entities.ContainerCreateReport{Id: response.ID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []string, options entities.ContainerLogsOptions) error {
|
func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIds []string, options entities.ContainerLogsOptions) error {
|
||||||
// The endpoint is not ready yet and requires some more work.
|
since := options.Since.Format(time.RFC3339)
|
||||||
return errors.New("not implemented yet")
|
tail := strconv.FormatInt(options.Tail, 10)
|
||||||
|
stdout := options.Writer != nil
|
||||||
|
opts := containers.LogOptions{
|
||||||
|
Follow: &options.Follow,
|
||||||
|
Since: &since,
|
||||||
|
Stderr: &stdout,
|
||||||
|
Stdout: &stdout,
|
||||||
|
Tail: &tail,
|
||||||
|
Timestamps: &options.Timestamps,
|
||||||
|
Until: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
outCh := make(chan string)
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
go func() {
|
||||||
|
err = containers.Logs(ic.ClientCxt, nameOrIds[0], opts, outCh, outCh)
|
||||||
|
cancel()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return err
|
||||||
|
case line := <-outCh:
|
||||||
|
_, _ = io.WriteString(options.Writer, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error {
|
func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error {
|
||||||
|
@ -89,10 +89,17 @@ func (p *PodmanTestIntegration) StartRemoteService() {
|
|||||||
if os.Geteuid() == 0 {
|
if os.Geteuid() == 0 {
|
||||||
os.MkdirAll("/run/podman", 0755)
|
os.MkdirAll("/run/podman", 0755)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args := []string{}
|
||||||
|
if _, found := os.LookupEnv("DEBUG_SERVICE"); found {
|
||||||
|
args = append(args, "--log-level", "debug")
|
||||||
|
}
|
||||||
remoteSocket := p.RemoteSocket
|
remoteSocket := p.RemoteSocket
|
||||||
args := []string{"system", "service", "--timeout", "0", remoteSocket}
|
args = append(args, "system", "service", "--timeout", "0", remoteSocket)
|
||||||
podmanOptions := getRemoteOptions(p, args)
|
podmanOptions := getRemoteOptions(p, args)
|
||||||
command := exec.Command(p.PodmanBinary, podmanOptions...)
|
command := exec.Command(p.PodmanBinary, podmanOptions...)
|
||||||
|
command.Stdout = os.Stdout
|
||||||
|
command.Stderr = os.Stderr
|
||||||
fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
|
fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
|
||||||
command.Start()
|
command.Start()
|
||||||
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
. "github.com/containers/libpod/test/utils"
|
. "github.com/containers/libpod/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
. "github.com/onsi/gomega/gexec"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Podman logs", func() {
|
var _ = Describe("Podman logs", func() {
|
||||||
@ -19,7 +20,6 @@ var _ = Describe("Podman logs", func() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
SkipIfRemote() // v2remotefail
|
|
||||||
tempdir, err = CreateTempDirInTempDir()
|
tempdir, err = CreateTempDirInTempDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -36,97 +36,99 @@ var _ = Describe("Podman logs", func() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs for container", func() {
|
It("all lines", func() {
|
||||||
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
|
||||||
|
|
||||||
|
cid := logc.OutputToString()
|
||||||
results := podmanTest.Podman([]string{"logs", cid})
|
results := podmanTest.Podman([]string{"logs", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs tail two lines", func() {
|
It("tail two lines", func() {
|
||||||
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--tail", "2", cid})
|
results := podmanTest.Podman([]string{"logs", "--tail", "2", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs tail zero lines", func() {
|
It("tail zero lines", func() {
|
||||||
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--tail", "0", cid})
|
results := podmanTest.Podman([]string{"logs", "--tail", "0", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(0))
|
Expect(len(results.OutputToStringArray())).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs tail 99 lines", func() {
|
It("tail 99 lines", func() {
|
||||||
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--tail", "99", cid})
|
results := podmanTest.Podman([]string{"logs", "--tail", "99", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs tail 2 lines with timestamps", func() {
|
It("tail 2 lines with timestamps", func() {
|
||||||
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--tail", "2", "-t", cid})
|
results := podmanTest.Podman([]string{"logs", "--tail", "2", "-t", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs latest with since time", func() {
|
It("since time 2017-08-07", func() {
|
||||||
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--since", "2017-08-07T10:10:09.056611202-04:00", cid})
|
results := podmanTest.Podman([]string{"logs", "--since", "2017-08-07T10:10:09.056611202-04:00", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs latest with since duration", func() {
|
It("since duration 10m", func() {
|
||||||
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--since", "10m", cid})
|
results := podmanTest.Podman([]string{"logs", "--since", "10m", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs latest and container name should fail", func() {
|
It("latest and container name should fail", func() {
|
||||||
|
SkipIfRemote() // -l not supported
|
||||||
results := podmanTest.Podman([]string{"logs", "-l", "foobar"})
|
results := podmanTest.Podman([]string{"logs", "-l", "foobar"})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results).To(ExitWithError())
|
Expect(results).To(ExitWithError())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs two containers and should display short container IDs", func() {
|
It("two containers showing short container IDs", func() {
|
||||||
|
SkipIfRemote() // remote does not support multiple containers
|
||||||
log1 := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
log1 := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
log1.WaitWithDefaultTimeout()
|
log1.WaitWithDefaultTimeout()
|
||||||
Expect(log1.ExitCode()).To(Equal(0))
|
Expect(log1.ExitCode()).To(Equal(0))
|
||||||
@ -139,7 +141,7 @@ var _ = Describe("Podman logs", func() {
|
|||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", cid1, cid2})
|
results := podmanTest.Podman([]string{"logs", cid1, cid2})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).Should(Exit(0))
|
||||||
|
|
||||||
output := results.OutputToStringArray()
|
output := results.OutputToStringArray()
|
||||||
Expect(len(output)).To(Equal(6))
|
Expect(len(output)).To(Equal(6))
|
||||||
@ -149,23 +151,24 @@ var _ = Describe("Podman logs", func() {
|
|||||||
It("podman logs on a created container should result in 0 exit code", func() {
|
It("podman logs on a created container should result in 0 exit code", func() {
|
||||||
session := podmanTest.Podman([]string{"create", "-dt", "--name", "log", ALPINE})
|
session := podmanTest.Podman([]string{"create", "-dt", "--name", "log", ALPINE})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(BeZero())
|
Expect(session).To(Exit(0))
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "log"})
|
results := podmanTest.Podman([]string{"logs", "log"})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(BeZero())
|
Expect(results).To(Exit(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs for container with container tag", func() {
|
It("using journald for container with container tag", func() {
|
||||||
|
SkipIfRemote()
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "--log-opt=tag={{.ImageName}}", "-d", ALPINE, "sh", "-c", "echo podman; sleep 0.1; echo podman; sleep 0.1; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "--log-opt=tag={{.ImageName}}", "-d", ALPINE, "sh", "-c", "echo podman; sleep 0.1; echo podman; sleep 0.1; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
wait := podmanTest.Podman([]string{"wait", "-l"})
|
wait := podmanTest.Podman([]string{"wait", "-l"})
|
||||||
wait.WaitWithDefaultTimeout()
|
wait.WaitWithDefaultTimeout()
|
||||||
Expect(wait.ExitCode()).To(BeZero())
|
Expect(wait).To(Exit(0))
|
||||||
|
|
||||||
cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_TAG", "-u", fmt.Sprintf("libpod-conmon-%s.scope", cid))
|
cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_TAG", "-u", fmt.Sprintf("libpod-conmon-%s.scope", cid))
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
@ -173,17 +176,18 @@ var _ = Describe("Podman logs", func() {
|
|||||||
Expect(string(out)).To(ContainSubstring("alpine"))
|
Expect(string(out)).To(ContainSubstring("alpine"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs for container name", func() {
|
It("using journald for container name", func() {
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
|
SkipIfRemote()
|
||||||
containerName := "inside-journal"
|
containerName := "inside-journal"
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-d", "--name", containerName, ALPINE, "sh", "-c", "echo podman; sleep 0.1; echo podman; sleep 0.1; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-d", "--name", containerName, ALPINE, "sh", "-c", "echo podman; sleep 0.1; echo podman; sleep 0.1; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
wait := podmanTest.Podman([]string{"wait", "-l"})
|
wait := podmanTest.Podman([]string{"wait", "-l"})
|
||||||
wait.WaitWithDefaultTimeout()
|
wait.WaitWithDefaultTimeout()
|
||||||
Expect(wait.ExitCode()).To(BeZero())
|
Expect(wait).To(Exit(0))
|
||||||
|
|
||||||
cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_NAME", "-u", fmt.Sprintf("libpod-conmon-%s.scope", cid))
|
cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_NAME", "-u", fmt.Sprintf("libpod-conmon-%s.scope", cid))
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
@ -191,98 +195,97 @@ var _ = Describe("Podman logs", func() {
|
|||||||
Expect(string(out)).To(ContainSubstring(containerName))
|
Expect(string(out)).To(ContainSubstring(containerName))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs for container", func() {
|
It("using journald for container", func() {
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", cid})
|
results := podmanTest.Podman([]string{"logs", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs tail two lines", func() {
|
It("using journald tail two lines", func() {
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--tail", "2", cid})
|
results := podmanTest.Podman([]string{"logs", "--tail", "2", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs tail 99 lines", func() {
|
It("using journald tail 99 lines", func() {
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--tail", "99", cid})
|
results := podmanTest.Podman([]string{"logs", "--tail", "99", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs tail 2 lines with timestamps", func() {
|
It("using journald tail 2 lines with timestamps", func() {
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--tail", "2", "-t", cid})
|
results := podmanTest.Podman([]string{"logs", "--tail", "2", "-t", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
Expect(len(results.OutputToStringArray())).To(Equal(2))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs latest with since time", func() {
|
It("using journald since time 2017-08-07", func() {
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--since", "2017-08-07T10:10:09.056611202-04:00", cid})
|
results := podmanTest.Podman([]string{"logs", "--since", "2017-08-07T10:10:09.056611202-04:00", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman journald logs latest with since duration", func() {
|
It("using journald with duration 10m", func() {
|
||||||
Skip("need to verify images have correct packages for journald")
|
Skip("need to verify images have correct packages for journald")
|
||||||
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--log-driver", "journald", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
cid := logc.OutputToString()
|
cid := logc.OutputToString()
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "--since", "10m", cid})
|
results := podmanTest.Podman([]string{"logs", "--since", "10m", cid})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
Expect(len(results.OutputToStringArray())).To(Equal(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman logs -f two lines", func() {
|
It("streaming output", func() {
|
||||||
containerName := "logs-f-rm"
|
containerName := "logs-f-rm"
|
||||||
|
|
||||||
logc := podmanTest.Podman([]string{"run", "--rm", "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman; sleep 1; echo podman"})
|
logc := podmanTest.Podman([]string{"run", "--rm", "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman; sleep 1; echo podman"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
|
|
||||||
results := podmanTest.Podman([]string{"logs", "-f", containerName})
|
results := podmanTest.Podman([]string{"logs", "-f", containerName})
|
||||||
results.WaitWithDefaultTimeout()
|
results.WaitWithDefaultTimeout()
|
||||||
Expect(results.ExitCode()).To(Equal(0))
|
Expect(results).To(Exit(0))
|
||||||
|
|
||||||
// Verify that the cleanup process worked correctly and we can recreate a container with the same name
|
// Verify that the cleanup process worked correctly and we can recreate a container with the same name
|
||||||
logc = podmanTest.Podman([]string{"run", "--rm", "--name", containerName, "-dt", ALPINE, "true"})
|
logc = podmanTest.Podman([]string{"run", "--rm", "--name", containerName, "-dt", ALPINE, "true"})
|
||||||
logc.WaitWithDefaultTimeout()
|
logc.WaitWithDefaultTimeout()
|
||||||
Expect(logc.ExitCode()).To(Equal(0))
|
Expect(logc).To(Exit(0))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user