mirror of https://github.com/containers/podman.git
logging: new mode -l passthrough
it allows to pass the current std streams down to the container. conmon support: https://github.com/containers/conmon/pull/289 [NO TESTS NEEDED] it needs a new conmon. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
869cb9a654
commit
3ce98a5ec2
|
@ -771,10 +771,13 @@ func AutocompleteImageVolume(cmd *cobra.Command, args []string, toComplete strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutocompleteLogDriver - Autocomplete log-driver options.
|
// AutocompleteLogDriver - Autocomplete log-driver options.
|
||||||
// -> "journald", "none", "k8s-file"
|
// -> "journald", "none", "k8s-file", "passthrough"
|
||||||
func AutocompleteLogDriver(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func AutocompleteLogDriver(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
// don't show json-file
|
// don't show json-file
|
||||||
logDrivers := []string{define.JournaldLogging, define.NoLogging, define.KubernetesLogging}
|
logDrivers := []string{define.JournaldLogging, define.NoLogging, define.KubernetesLogging}
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
logDrivers = append(logDrivers, define.PassthroughLogging)
|
||||||
|
}
|
||||||
return logDrivers, cobra.ShellCompDirectiveNoFileComp
|
return logDrivers, cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/containers/podman/v3/pkg/specgen"
|
"github.com/containers/podman/v3/pkg/specgen"
|
||||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||||
"github.com/containers/podman/v3/pkg/util"
|
"github.com/containers/podman/v3/pkg/util"
|
||||||
|
"github.com/mattn/go-isatty"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -161,7 +162,9 @@ func create(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cliVals.LogDriver != define.PassthroughLogging {
|
||||||
fmt.Println(report.Id)
|
fmt.Println(report.Id)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +191,14 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
|
||||||
vals.UserNS = "private"
|
vals.UserNS = "private"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if cliVals.LogDriver == define.PassthroughLogging {
|
||||||
|
if isatty.IsTerminal(0) || isatty.IsTerminal(1) || isatty.IsTerminal(2) {
|
||||||
|
return vals, errors.New("the '--log-driver passthrough' option cannot be used on a TTY")
|
||||||
|
}
|
||||||
|
if registry.IsRemote() {
|
||||||
|
return vals, errors.New("the '--log-driver passthrough' option is not supported in remote mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !isInfra {
|
if !isInfra {
|
||||||
if c.Flag("shm-size").Changed {
|
if c.Flag("shm-size").Changed {
|
||||||
|
|
|
@ -158,8 +158,13 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
runOpts.InputStream = nil
|
runOpts.InputStream = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
passthrough := cliVals.LogDriver == define.PassthroughLogging
|
||||||
|
|
||||||
// If attach is set, clear stdin/stdout/stderr and only attach requested
|
// If attach is set, clear stdin/stdout/stderr and only attach requested
|
||||||
if cmd.Flag("attach").Changed {
|
if cmd.Flag("attach").Changed {
|
||||||
|
if passthrough {
|
||||||
|
return errors.Wrapf(define.ErrInvalidArg, "cannot specify --attach with --log-driver=passthrough")
|
||||||
|
}
|
||||||
runOpts.OutputStream = nil
|
runOpts.OutputStream = nil
|
||||||
runOpts.ErrorStream = nil
|
runOpts.ErrorStream = nil
|
||||||
if !cliVals.Interactive {
|
if !cliVals.Interactive {
|
||||||
|
@ -179,6 +184,7 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cliVals.PreserveFDs = runOpts.PreserveFDs
|
cliVals.PreserveFDs = runOpts.PreserveFDs
|
||||||
s := specgen.NewSpecGenerator(imageName, cliVals.RootFS)
|
s := specgen.NewSpecGenerator(imageName, cliVals.RootFS)
|
||||||
if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil {
|
if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil {
|
||||||
|
@ -200,7 +206,7 @@ func run(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if runOpts.Detach {
|
if runOpts.Detach && !passthrough {
|
||||||
fmt.Println(report.Id)
|
fmt.Println(report.Id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,7 +513,11 @@ Not implemented
|
||||||
|
|
||||||
#### **--log-driver**="*k8s-file*"
|
#### **--log-driver**="*k8s-file*"
|
||||||
|
|
||||||
Logging driver for the container. Currently available options are *k8s-file*, *journald*, and *none*, with *json-file* aliased to *k8s-file* for scripting compatibility.
|
Logging driver for the container. Currently available options are *k8s-file*, *journald*, *none* and *passthrough*, with *json-file* aliased to *k8s-file* for scripting compatibility.
|
||||||
|
|
||||||
|
The *passthrough* driver passes down the standard streams (stdin, stdout, stderr) to the
|
||||||
|
container. It is not allowed with the remote Podman client and on a tty, since it is
|
||||||
|
vulnerable to attacks via TIOCSTI.
|
||||||
|
|
||||||
#### **--log-opt**=*name*=*value*
|
#### **--log-opt**=*name*=*value*
|
||||||
|
|
||||||
|
|
|
@ -538,7 +538,12 @@ Not implemented.
|
||||||
|
|
||||||
#### **--log-driver**="*driver*"
|
#### **--log-driver**="*driver*"
|
||||||
|
|
||||||
Logging driver for the container. Currently available options are **k8s-file**, **journald**, and **none**, with **json-file** aliased to **k8s-file** for scripting compatibility.
|
Logging driver for the container. Currently available options are **k8s-file**, **journald**, **none** and **passthrough**, with **json-file** aliased to **k8s-file** for scripting compatibility.
|
||||||
|
|
||||||
|
The **passthrough** driver passes down the standard streams (stdin, stdout, stderr) to the
|
||||||
|
container. It is not allowed with the remote Podman client and on a tty, since it is
|
||||||
|
vulnerable to attacks via TIOCSTI.
|
||||||
|
|
||||||
|
|
||||||
#### **--log-opt**=*name*=*value*
|
#### **--log-opt**=*name*=*value*
|
||||||
|
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -41,6 +41,7 @@ require (
|
||||||
github.com/hpcloud/tail v1.0.0
|
github.com/hpcloud/tail v1.0.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
|
||||||
github.com/mrunalp/fileutils v0.5.0
|
github.com/mrunalp/fileutils v0.5.0
|
||||||
github.com/onsi/ginkgo v1.16.4
|
github.com/onsi/ginkgo v1.16.4
|
||||||
|
|
|
@ -229,6 +229,10 @@ func (c *Container) Kill(signal uint) error {
|
||||||
// This function returns when the attach finishes. It does not hold the lock for
|
// This function returns when the attach finishes. It does not hold the lock for
|
||||||
// the duration of its runtime, only using it at the beginning to verify state.
|
// the duration of its runtime, only using it at the beginning to verify state.
|
||||||
func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize) error {
|
func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize) error {
|
||||||
|
switch c.LogDriver() {
|
||||||
|
case define.PassthroughLogging:
|
||||||
|
return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot attach")
|
||||||
|
}
|
||||||
if !c.batched {
|
if !c.batched {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
if err := c.syncContainer(); err != nil {
|
if err := c.syncContainer(); err != nil {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
var logDrivers []string
|
var logDrivers []string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
logDrivers = append(logDrivers, define.KubernetesLogging, define.NoLogging)
|
logDrivers = append(logDrivers, define.KubernetesLogging, define.NoLogging, define.PassthroughLogging)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log is a runtime function that can read one or more container logs.
|
// Log is a runtime function that can read one or more container logs.
|
||||||
|
@ -34,6 +34,8 @@ func (r *Runtime) Log(ctx context.Context, containers []*Container, options *log
|
||||||
// ReadLog reads a containers log based on the input options and returns log lines over a channel.
|
// ReadLog reads a containers log based on the input options and returns log lines over a channel.
|
||||||
func (c *Container) ReadLog(ctx context.Context, 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() {
|
switch c.LogDriver() {
|
||||||
|
case define.PassthroughLogging:
|
||||||
|
return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot read logs")
|
||||||
case define.NoLogging:
|
case define.NoLogging:
|
||||||
return errors.Wrapf(define.ErrNoLogs, "this container is using the 'none' log driver, cannot read logs")
|
return errors.Wrapf(define.ErrNoLogs, "this container is using the 'none' log driver, cannot read logs")
|
||||||
case define.JournaldLogging:
|
case define.JournaldLogging:
|
||||||
|
|
|
@ -78,6 +78,9 @@ const JSONLogging = "json-file"
|
||||||
// NoLogging is the string conmon expects when specifying to use no log driver whatsoever
|
// NoLogging is the string conmon expects when specifying to use no log driver whatsoever
|
||||||
const NoLogging = "none"
|
const NoLogging = "none"
|
||||||
|
|
||||||
|
// PassthroughLogging is the string conmon expects when specifying to use the passthrough driver
|
||||||
|
const PassthroughLogging = "passthrough"
|
||||||
|
|
||||||
// Strings used for --sdnotify option to podman
|
// Strings used for --sdnotify option to podman
|
||||||
const (
|
const (
|
||||||
SdNotifyModeContainer = "container"
|
SdNotifyModeContainer = "container"
|
||||||
|
|
|
@ -40,7 +40,9 @@ func openUnixSocket(path string) (*net.UnixConn, error) {
|
||||||
// Does not check if state is appropriate
|
// Does not check if state is appropriate
|
||||||
// started is only required if startContainer is true
|
// started is only required if startContainer is true
|
||||||
func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error {
|
func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error {
|
||||||
if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
|
passthrough := c.LogDriver() == define.PassthroughLogging
|
||||||
|
|
||||||
|
if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput && !passthrough {
|
||||||
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
|
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
|
||||||
}
|
}
|
||||||
if startContainer && started == nil {
|
if startContainer && started == nil {
|
||||||
|
@ -52,6 +54,8 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var conn *net.UnixConn
|
||||||
|
if !passthrough {
|
||||||
logrus.Debugf("Attaching to container %s", c.ID())
|
logrus.Debugf("Attaching to container %s", c.ID())
|
||||||
|
|
||||||
registerResizeFunc(resize, c.bundlePath())
|
registerResizeFunc(resize, c.bundlePath())
|
||||||
|
@ -61,15 +65,16 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := openUnixSocket(attachSock)
|
conn, err = openUnixSocket(attachSock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
|
return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := conn.Close(); err != nil {
|
if err := conn.Close(); err != nil {
|
||||||
logrus.Errorf("Unable to close socket: %q", err)
|
logrus.Errorf("unable to close socket: %q", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
// If starting was requested, start the container and notify when that's
|
// If starting was requested, start the container and notify when that's
|
||||||
// done.
|
// done.
|
||||||
|
@ -80,6 +85,10 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
|
||||||
started <- true
|
started <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if passthrough {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys)
|
receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys)
|
||||||
if attachRdy != nil {
|
if attachRdy != nil {
|
||||||
attachRdy <- true
|
attachRdy <- true
|
||||||
|
|
|
@ -1288,6 +1288,8 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
|
||||||
logDriverArg = define.JournaldLogging
|
logDriverArg = define.JournaldLogging
|
||||||
case define.NoLogging:
|
case define.NoLogging:
|
||||||
logDriverArg = define.NoLogging
|
logDriverArg = define.NoLogging
|
||||||
|
case define.PassthroughLogging:
|
||||||
|
logDriverArg = define.PassthroughLogging
|
||||||
case define.JSONLogging:
|
case define.JSONLogging:
|
||||||
fallthrough
|
fallthrough
|
||||||
//lint:ignore ST1015 the default case has to be here
|
//lint:ignore ST1015 the default case has to be here
|
||||||
|
|
|
@ -1114,7 +1114,7 @@ func WithLogDriver(driver string) CtrCreateOption {
|
||||||
switch driver {
|
switch driver {
|
||||||
case "":
|
case "":
|
||||||
return errors.Wrapf(define.ErrInvalidArg, "log driver must be set")
|
return errors.Wrapf(define.ErrInvalidArg, "log driver must be set")
|
||||||
case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging:
|
case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging, define.PassthroughLogging:
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return errors.Wrapf(define.ErrInvalidArg, "invalid log driver")
|
return errors.Wrapf(define.ErrInvalidArg, "invalid log driver")
|
||||||
|
|
|
@ -473,7 +473,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ctr.config.LogDriver {
|
switch ctr.config.LogDriver {
|
||||||
case define.NoLogging:
|
case define.NoLogging, define.PassthroughLogging:
|
||||||
break
|
break
|
||||||
case define.JournaldLogging:
|
case define.JournaldLogging:
|
||||||
ctr.initializeJournal(ctx)
|
ctr.initializeJournal(ctx)
|
||||||
|
|
Loading…
Reference in New Issue