diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/adapter/containers.go | 66 | ||||
-rw-r--r-- | pkg/util/utils.go | 31 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 2 |
3 files changed, 97 insertions, 2 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index d575bc9b0..0721af773 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -3,6 +3,7 @@ package adapter import ( + "bufio" "context" "fmt" "io/ioutil" @@ -19,6 +20,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/adapter/shortcuts" "github.com/containers/libpod/pkg/systemdgen" + "github.com/containers/psgo" "github.com/containers/storage" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -822,7 +824,69 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) { if err != nil { return nil, errors.Wrapf(err, "unable to lookup requested container") } - return container.Top(descriptors) + + output, psgoErr := container.Top(descriptors) + if psgoErr == nil { + return output, nil + } + + // If we encountered an ErrUnknownDescriptor error, fallback to executing + // ps(1). This ensures backwards compatibility to users depending on ps(1) + // and makes sure we're ~compatible with docker. + if errors.Cause(psgoErr) != psgo.ErrUnknownDescriptor { + return nil, psgoErr + } + + output, err = r.execPS(container, descriptors) + if err != nil { + // Note: return psgoErr to guide users into using the AIX descriptors + // instead of using ps(1). + return nil, psgoErr + } + + // Trick: filter the ps command from the output instead of + // checking/requiring PIDs in the output. + filtered := []string{} + cmd := strings.Join(descriptors, " ") + for _, line := range output { + if !strings.Contains(line, cmd) { + filtered = append(filtered, line) + } + } + + return filtered, nil +} + +func (r *LocalRuntime) execPS(c *libpod.Container, args []string) ([]string, error) { + rPipe, wPipe, err := os.Pipe() + if err != nil { + return nil, err + } + defer wPipe.Close() + defer rPipe.Close() + + streams := new(libpod.AttachStreams) + streams.OutputStream = wPipe + streams.ErrorStream = wPipe + streams.InputStream = os.Stdin + streams.AttachOutput = true + streams.AttachError = true + streams.AttachInput = true + + psOutput := []string{} + go func() { + scanner := bufio.NewScanner(rPipe) + for scanner.Scan() { + psOutput = append(psOutput, scanner.Text()) + } + }() + + cmd := append([]string{"ps"}, args...) + if err := c.Exec(false, false, []string{}, cmd, "", "", streams, 0); err != nil { + return nil, err + } + + return psOutput, nil } // Prune removes stopped containers diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 14b0c2b55..2a52e5129 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -10,10 +10,12 @@ import ( "github.com/BurntSushi/toml" "github.com/containers/image/types" + "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + "github.com/spf13/pflag" "golang.org/x/crypto/ssh/terminal" ) @@ -252,3 +254,32 @@ func ParseInputTime(inputTime string) (time.Time, error) { } return time.Now().Add(-duration), nil } + +// GetGlobalOpts checks all global flags and generates the command string +func GetGlobalOpts(c *cliconfig.RunlabelValues) string { + globalFlags := map[string]bool{ + "cgroup-manager": true, "cni-config-dir": true, "conmon": true, "default-mounts-file": true, + "hooks-dir": true, "namespace": true, "root": true, "runroot": true, + "runtime": true, "storage-driver": true, "storage-opt": true, "syslog": true, + "trace": true, "network-cmd-path": true, "config": true, "cpu-profile": true, + "log-level": true, "tmpdir": true} + const stringSliceType string = "stringSlice" + + var optsCommand []string + c.PodmanCommand.Command.Flags().VisitAll(func(f *pflag.Flag) { + if !f.Changed { + return + } + if _, exist := globalFlags[f.Name]; exist { + if f.Value.Type() == stringSliceType { + flagValue := strings.TrimSuffix(strings.TrimPrefix(f.Value.String(), "["), "]") + for _, value := range strings.Split(flagValue, ",") { + optsCommand = append(optsCommand, fmt.Sprintf("--%s %s", f.Name, value)) + } + } else { + optsCommand = append(optsCommand, fmt.Sprintf("--%s %s", f.Name, f.Value.String())) + } + } + }) + return strings.Join(optsCommand, " ") +} diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index cecddf6b3..20f82a1c6 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -728,7 +728,7 @@ func (i *LibpodAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman. return call.ReplyErrorOccurred(fmt.Sprintf("%s does not contain the label %s", input.Image, input.Label)) } - cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, input.Name, input.Opts, input.ExtraArgs) + cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, input.Name, input.Opts, input.ExtraArgs, "") if err != nil { return call.ReplyErrorOccurred(err.Error()) } |