diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2021-09-01 11:36:26 +0200 |
---|---|---|
committer | Giuseppe Scrivano <gscrivan@redhat.com> | 2021-09-27 12:07:01 +0200 |
commit | 3ce98a5ec28840f2d7836a002a156974f37f6c0e (patch) | |
tree | e684194119ec89281b72b73569052d423d96a6ad | |
parent | 869cb9a65413cc99bf8ed0e158c0e2f7b0df513a (diff) | |
download | podman-3ce98a5ec28840f2d7836a002a156974f37f6c0e.tar.gz podman-3ce98a5ec28840f2d7836a002a156974f37f6c0e.tar.bz2 podman-3ce98a5ec28840f2d7836a002a156974f37f6c0e.zip |
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>
-rw-r--r-- | cmd/podman/common/completion.go | 5 | ||||
-rw-r--r-- | cmd/podman/containers/create.go | 13 | ||||
-rw-r--r-- | cmd/podman/containers/run.go | 8 | ||||
-rw-r--r-- | docs/source/markdown/podman-create.1.md | 6 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md | 7 | ||||
-rw-r--r-- | go.mod | 1 | ||||
-rw-r--r-- | libpod/container_api.go | 4 | ||||
-rw-r--r-- | libpod/container_log.go | 4 | ||||
-rw-r--r-- | libpod/define/config.go | 3 | ||||
-rw-r--r-- | libpod/oci_attach_linux.go | 39 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 2 | ||||
-rw-r--r-- | libpod/options.go | 2 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 2 |
13 files changed, 73 insertions, 23 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 90522438d..ea453a331 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -771,10 +771,13 @@ func AutocompleteImageVolume(cmd *cobra.Command, args []string, toComplete strin } // 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) { // don't show json-file logDrivers := []string{define.JournaldLogging, define.NoLogging, define.KubernetesLogging} + if !registry.IsRemote() { + logDrivers = append(logDrivers, define.PassthroughLogging) + } return logDrivers, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 8b27de53e..2593b4c44 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -19,6 +19,7 @@ import ( "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/specgenutil" "github.com/containers/podman/v3/pkg/util" + "github.com/mattn/go-isatty" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -161,7 +162,9 @@ func create(cmd *cobra.Command, args []string) error { } } - fmt.Println(report.Id) + if cliVals.LogDriver != define.PassthroughLogging { + fmt.Println(report.Id) + } return nil } @@ -188,6 +191,14 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra 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 c.Flag("shm-size").Changed { diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index d14961829..071708b76 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -158,8 +158,13 @@ func run(cmd *cobra.Command, args []string) error { runOpts.InputStream = nil } + passthrough := cliVals.LogDriver == define.PassthroughLogging + // If attach is set, clear stdin/stdout/stderr and only attach requested if cmd.Flag("attach").Changed { + if passthrough { + return errors.Wrapf(define.ErrInvalidArg, "cannot specify --attach with --log-driver=passthrough") + } runOpts.OutputStream = nil runOpts.ErrorStream = nil if !cliVals.Interactive { @@ -179,6 +184,7 @@ func run(cmd *cobra.Command, args []string) error { } } } + cliVals.PreserveFDs = runOpts.PreserveFDs s := specgen.NewSpecGenerator(imageName, cliVals.RootFS) if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil { @@ -200,7 +206,7 @@ func run(cmd *cobra.Command, args []string) error { return err } - if runOpts.Detach { + if runOpts.Detach && !passthrough { fmt.Println(report.Id) return nil } diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index f63f5ca9c..0630c8be9 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -513,7 +513,11 @@ Not implemented #### **--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* diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 6d68fd62b..43b6d5cc6 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -538,7 +538,12 @@ Not implemented. #### **--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* @@ -41,6 +41,7 @@ require ( github.com/hpcloud/tail v1.0.0 github.com/json-iterator/go v1.1.12 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/mrunalp/fileutils v0.5.0 github.com/onsi/ginkgo v1.16.4 diff --git a/libpod/container_api.go b/libpod/container_api.go index 2d5b07a35..50be0eea4 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -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 // 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 { + switch c.LogDriver() { + case define.PassthroughLogging: + return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot attach") + } if !c.batched { c.lock.Lock() if err := c.syncContainer(); err != nil { diff --git a/libpod/container_log.go b/libpod/container_log.go index a65b2a44f..18840bff2 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -18,7 +18,7 @@ import ( var logDrivers []string 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. @@ -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. func (c *Container) ReadLog(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine) error { 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: return errors.Wrapf(define.ErrNoLogs, "this container is using the 'none' log driver, cannot read logs") case define.JournaldLogging: diff --git a/libpod/define/config.go b/libpod/define/config.go index 6c426f2ec..7a0d39e42 100644 --- a/libpod/define/config.go +++ b/libpod/define/config.go @@ -78,6 +78,9 @@ const JSONLogging = "json-file" // NoLogging is the string conmon expects when specifying to use no log driver whatsoever 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 const ( SdNotifyModeContainer = "container" diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index 9ae46eeda..d4d4a1076 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -40,7 +40,9 @@ func openUnixSocket(path string) (*net.UnixConn, error) { // Does not check if state is appropriate // 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 { - 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") } if startContainer && started == nil { @@ -52,24 +54,27 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <- return err } - logrus.Debugf("Attaching to container %s", c.ID()) + var conn *net.UnixConn + if !passthrough { + logrus.Debugf("Attaching to container %s", c.ID()) - registerResizeFunc(resize, c.bundlePath()) + registerResizeFunc(resize, c.bundlePath()) - attachSock, err := c.AttachSocketPath() - if err != nil { - return err - } + attachSock, err := c.AttachSocketPath() + if err != nil { + return err + } - conn, err := openUnixSocket(attachSock) - if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock) - } - defer func() { - if err := conn.Close(); err != nil { - logrus.Errorf("Unable to close socket: %q", err) + conn, err = openUnixSocket(attachSock) + if err != nil { + return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock) } - }() + defer func() { + if err := conn.Close(); err != nil { + logrus.Errorf("unable to close socket: %q", err) + } + }() + } // If starting was requested, start the container and notify when that's // done. @@ -80,6 +85,10 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <- started <- true } + if passthrough { + return nil + } + receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys) if attachRdy != nil { attachRdy <- true diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 56c7a90aa..b7b5d09cd 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -1288,6 +1288,8 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p logDriverArg = define.JournaldLogging case define.NoLogging: logDriverArg = define.NoLogging + case define.PassthroughLogging: + logDriverArg = define.PassthroughLogging case define.JSONLogging: fallthrough //lint:ignore ST1015 the default case has to be here diff --git a/libpod/options.go b/libpod/options.go index a80f51c6a..553af43fd 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1114,7 +1114,7 @@ func WithLogDriver(driver string) CtrCreateOption { switch driver { case "": 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 default: return errors.Wrapf(define.ErrInvalidArg, "invalid log driver") diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 9a4dbf626..3494fa8f2 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -473,7 +473,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai } switch ctr.config.LogDriver { - case define.NoLogging: + case define.NoLogging, define.PassthroughLogging: break case define.JournaldLogging: ctr.initializeJournal(ctx) |