summaryrefslogtreecommitdiff
path: root/pkg/adapter
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/adapter')
-rw-r--r--pkg/adapter/containers.go84
-rw-r--r--pkg/adapter/containers_remote.go5
2 files changed, 88 insertions, 1 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index eb90ab50e..0721af773 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -3,6 +3,7 @@
package adapter
import (
+ "bufio"
"context"
"fmt"
"io/ioutil"
@@ -18,6 +19,8 @@ import (
"github.com/containers/libpod/cmd/podman/shared"
"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"
@@ -821,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
@@ -940,3 +1005,20 @@ func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) {
}
return portContainers, nil
}
+
+// GenerateSystemd creates a unit file for a container
+func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
+ ctr, err := r.Runtime.LookupContainer(c.InputArgs[0])
+ if err != nil {
+ return "", err
+ }
+ timeout := int(ctr.StopTimeout())
+ if c.StopTimeout >= 0 {
+ timeout = int(c.StopTimeout)
+ }
+ name := ctr.ID()
+ if c.Name {
+ name = ctr.Name()
+ }
+ return systemdgen.CreateSystemdUnitAsString(name, ctr.ID(), c.RestartPolicy, ctr.Config().StaticDir, timeout)
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index b7e353f71..201249fc3 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -956,3 +956,8 @@ func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) {
}
return containers, nil
}
+
+// GenerateSystemd creates a systemd until for a container
+func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
+ return iopodman.GenerateSystemd().Call(r.Conn, c.InputArgs[0], c.RestartPolicy, int64(c.StopTimeout), c.Name)
+}