summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/cliconfig/config.go4
-rw-r--r--cmd/podman/cliconfig/create.go1
-rw-r--r--cmd/podman/commands.go16
-rw-r--r--cmd/podman/commands_remoteclient.go10
-rw-r--r--cmd/podman/cp.go21
-rw-r--r--cmd/podman/create.go25
-rw-r--r--cmd/podman/healthcheck.go25
-rw-r--r--cmd/podman/healthcheck_run.go53
-rw-r--r--cmd/podman/imagefilters/filters.go24
-rw-r--r--cmd/podman/images.go3
-rw-r--r--cmd/podman/main.go1
-rw-r--r--cmd/podman/play_kube.go51
-rw-r--r--cmd/podman/pod.go3
-rw-r--r--cmd/podman/pod_stats.go47
-rw-r--r--cmd/podman/pod_top.go31
-rw-r--r--cmd/podman/varlink/io.podman.varlink15
-rw-r--r--cmd/podman/wait.go53
17 files changed, 267 insertions, 116 deletions
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index ea99aafc2..7945cb6cb 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -217,6 +217,10 @@ type PauseValues struct {
All bool
}
+type HealthCheckValues struct {
+ PodmanCommand
+}
+
type KubePlayValues struct {
PodmanCommand
Authfile string
diff --git a/cmd/podman/cliconfig/create.go b/cmd/podman/cliconfig/create.go
index b5ca1be9c..49ab3d827 100644
--- a/cmd/podman/cliconfig/create.go
+++ b/cmd/podman/cliconfig/create.go
@@ -23,4 +23,5 @@ type BuildValues struct {
type CpValues struct {
PodmanCommand
+ Extract bool
}
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index c261e54e2..d37af70c1 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -35,7 +35,6 @@ func getMainCommands() []*cobra.Command {
_topCommand,
_umountCommand,
_unpauseCommand,
- _waitCommand,
}
if len(_varlinkCommand.Use) > 0 {
@@ -85,14 +84,6 @@ func getContainerSubCommands() []*cobra.Command {
}
}
-// Commands that the local client implements
-func getPodSubCommands() []*cobra.Command {
- return []*cobra.Command{
- _podStatsCommand,
- _podTopCommand,
- }
-}
-
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{
_containerKubeCommand,
@@ -121,3 +112,10 @@ func getSystemSubCommands() []*cobra.Command {
_renumberCommand,
}
}
+
+// Commands that the local client implements
+func getHealtcheckSubCommands() []*cobra.Command {
+ return []*cobra.Command{
+ _healthcheckrunCommand,
+ }
+}
diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go
index 081043b25..9b09e7dbc 100644
--- a/cmd/podman/commands_remoteclient.go
+++ b/cmd/podman/commands_remoteclient.go
@@ -29,11 +29,6 @@ func getContainerSubCommands() []*cobra.Command {
}
// commands that only the remoteclient implements
-func getPodSubCommands() []*cobra.Command {
- return []*cobra.Command{}
-}
-
-// commands that only the remoteclient implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
@@ -52,3 +47,8 @@ func getTrustSubCommands() []*cobra.Command {
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+
+// Commands that the remoteclient implements
+func getHealtcheckSubCommands() []*cobra.Command {
+ return []*cobra.Command{}
+}
diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go
index 5958370b6..a3411b158 100644
--- a/cmd/podman/cp.go
+++ b/cmd/podman/cp.go
@@ -43,6 +43,8 @@ var (
func init() {
cpCommand.Command = _cpCommand
+ flags := cpCommand.Flags()
+ flags.BoolVar(&cpCommand.Extract, "extract", false, "Extract the tar file into the destination directory.")
rootCmd.AddCommand(cpCommand.Command)
}
@@ -61,10 +63,11 @@ func cpCmd(c *cliconfig.CpValues) error {
}
defer runtime.Shutdown(false)
- return copyBetweenHostAndContainer(runtime, args[0], args[1])
+ extract := c.Flag("extract").Changed
+ return copyBetweenHostAndContainer(runtime, args[0], args[1], extract)
}
-func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest string) error {
+func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest string, extract bool) error {
srcCtr, srcPath := parsePath(runtime, src)
destCtr, destPath := parsePath(runtime, dest)
@@ -166,7 +169,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
var lastError error
for _, src := range glob {
- err := copy(src, destPath, dest, idMappingOpts, &containerOwner)
+ err := copy(src, destPath, dest, idMappingOpts, &containerOwner, extract)
if lastError != nil {
logrus.Error(lastError)
}
@@ -219,7 +222,7 @@ func getPathInfo(path string) (string, os.FileInfo, error) {
return path, srcfi, nil
}
-func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair) error {
+func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair, extract bool) error {
srcPath, err := filepath.EvalSymlinks(src)
if err != nil {
return errors.Wrapf(err, "error evaluating symlinks %q", srcPath)
@@ -240,6 +243,7 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
// return functions for copying items
copyFileWithTar := chrootarchive.CopyFileWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
copyWithTar := chrootarchive.CopyWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
+ untarPath := chrootarchive.UntarPathAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
if srcfi.IsDir() {
@@ -263,6 +267,15 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
destPath = filepath.Join(destPath, filepath.Base(srcPath))
}
}
+
+ if extract {
+ // We're extracting an archive into the destination directory.
+ logrus.Debugf("extracting contents of %q into %q", srcPath, destPath)
+ if err = untarPath(srcPath, destPath); err != nil {
+ return errors.Wrapf(err, "error extracting %q into %q", srcPath, destPath)
+ }
+ return nil
+ }
// Copy the file, preserving attributes.
logrus.Debugf("copying %q to %q", srcPath, destPath)
if err = copyFileWithTar(srcPath, destPath); err != nil {
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 129c886b2..a7b9bbf31 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -12,6 +12,7 @@ import (
"strings"
"syscall"
+ "github.com/containers/image/manifest"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
@@ -117,6 +118,10 @@ func createInit(c *cliconfig.PodmanCommand) error {
}
func createContainer(c *cliconfig.PodmanCommand, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
+ var (
+ hasHealthCheck bool
+ healthCheck *manifest.Schema2HealthConfig
+ )
if c.Bool("trace") {
span, _ := opentracing.StartSpanFromContext(Ctx, "createContainer")
defer span.Finish()
@@ -163,12 +168,32 @@ func createContainer(c *cliconfig.PodmanCommand, runtime *libpod.Runtime) (*libp
} else {
imageName = newImage.ID()
}
+
+ // add healthcheck if it exists AND is correct mediatype
+ _, mediaType, err := newImage.Manifest(ctx)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "unable to determine mediatype of image %s", newImage.ID())
+ }
+ if mediaType == manifest.DockerV2Schema2MediaType {
+ healthCheck, err = newImage.GetHealthCheck(ctx)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "unable to get healthcheck for %s", c.InputArgs[0])
+ }
+ if healthCheck != nil {
+ hasHealthCheck = true
+ }
+ }
}
createConfig, err := parseCreateOpts(ctx, c, runtime, imageName, data)
if err != nil {
return nil, nil, err
}
+ // Because parseCreateOpts does derive anything from the image, we add health check
+ // at this point. The rest is done by WithOptions.
+ createConfig.HasHealthCheck = hasHealthCheck
+ createConfig.HealthCheck = healthCheck
+
ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx, nil)
if err != nil {
return nil, nil, err
diff --git a/cmd/podman/healthcheck.go b/cmd/podman/healthcheck.go
new file mode 100644
index 000000000..e7cc125cc
--- /dev/null
+++ b/cmd/podman/healthcheck.go
@@ -0,0 +1,25 @@
+package main
+
+import (
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/spf13/cobra"
+)
+
+var healthcheckDescription = "Manage health checks on containers"
+var healthcheckCommand = cliconfig.PodmanCommand{
+ Command: &cobra.Command{
+ Use: "healthcheck",
+ Short: "Manage Healthcheck",
+ Long: healthcheckDescription,
+ },
+}
+
+// Commands that are universally implemented
+var healthcheckCommands []*cobra.Command
+
+func init() {
+ healthcheckCommand.AddCommand(healthcheckCommands...)
+ healthcheckCommand.AddCommand(getHealtcheckSubCommands()...)
+ healthcheckCommand.SetUsageTemplate(UsageTemplate())
+ rootCmd.AddCommand(healthcheckCommand.Command)
+}
diff --git a/cmd/podman/healthcheck_run.go b/cmd/podman/healthcheck_run.go
new file mode 100644
index 000000000..d92b2ac01
--- /dev/null
+++ b/cmd/podman/healthcheck_run.go
@@ -0,0 +1,53 @@
+package main
+
+import (
+ "fmt"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ healthcheckRunCommand cliconfig.HealthCheckValues
+ healthcheckRunDescription = "run the health check of a container"
+ _healthcheckrunCommand = &cobra.Command{
+ Use: "run [flags] CONTAINER",
+ Short: "run the health check of a container",
+ Long: healthcheckRunDescription,
+ Example: `podman healthcheck run mywebapp`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ healthcheckRunCommand.InputArgs = args
+ healthcheckRunCommand.GlobalFlags = MainGlobalOpts
+ return healthCheckCmd(&healthcheckRunCommand)
+ },
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) < 1 || len(args) > 1 {
+ return errors.New("must provide the name or ID of one container")
+ }
+ return nil
+ },
+ }
+)
+
+func init() {
+ healthcheckRunCommand.Command = _healthcheckrunCommand
+ healthcheckRunCommand.SetUsageTemplate(UsageTemplate())
+}
+
+func healthCheckCmd(c *cliconfig.HealthCheckValues) error {
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
+ if err != nil {
+ return errors.Wrap(err, "could not get runtime")
+ }
+ status, err := runtime.HealthCheck(c)
+ if err != nil {
+ if status == libpod.HealthCheckFailure {
+ fmt.Println("\nunhealthy")
+ }
+ return err
+ }
+ fmt.Println("\nhealthy")
+ return nil
+}
diff --git a/cmd/podman/imagefilters/filters.go b/cmd/podman/imagefilters/filters.go
index d01eb7436..2932d61c0 100644
--- a/cmd/podman/imagefilters/filters.go
+++ b/cmd/podman/imagefilters/filters.go
@@ -2,11 +2,14 @@ package imagefilters
import (
"context"
+ "fmt"
+ "path/filepath"
"strings"
"time"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/inspect"
+ "github.com/sirupsen/logrus"
)
// ResultFilter is a mock function for image filtering
@@ -61,6 +64,27 @@ func LabelFilter(ctx context.Context, labelfilter string) ResultFilter {
}
}
+// ReferenceFilter allows you to filter by image name
+// Replacing all '/' with '|' so that filepath.Match() can work
+// '|' character is not valid in image name, so this is safe
+func ReferenceFilter(ctx context.Context, referenceFilter string) ResultFilter {
+ filter := fmt.Sprintf("*%s*", referenceFilter)
+ filter = strings.Replace(filter, "/", "|", -1)
+ return func(i *adapter.ContainerImage) bool {
+ for _, name := range i.Names() {
+ newName := strings.Replace(name, "/", "|", -1)
+ match, err := filepath.Match(filter, newName)
+ if err != nil {
+ logrus.Errorf("failed to match %s and %s, %q", name, referenceFilter, err)
+ }
+ if match {
+ return true
+ }
+ }
+ return false
+ }
+}
+
// OutputImageFilter allows you to filter by an a specific image name
func OutputImageFilter(userImage *adapter.ContainerImage) ResultFilter {
return func(i *adapter.ContainerImage) bool {
diff --git a/cmd/podman/images.go b/cmd/podman/images.go
index 26e51bef7..a4f2e5e10 100644
--- a/cmd/podman/images.go
+++ b/cmd/podman/images.go
@@ -375,6 +375,9 @@ func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, filters []s
case "label":
labelFilter := strings.Join(splitFilter[1:], "=")
filterFuncs = append(filterFuncs, imagefilters.LabelFilter(ctx, labelFilter))
+ case "reference":
+ referenceFilter := strings.Join(splitFilter[1:], "=")
+ filterFuncs = append(filterFuncs, imagefilters.ReferenceFilter(ctx, referenceFilter))
default:
return nil, errors.Errorf("invalid filter %s ", splitFilter[0])
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index b3faf05c0..97ffa8930 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -52,6 +52,7 @@ var mainCommands = []*cobra.Command{
_stopCommand,
_tagCommand,
_versionCommand,
+ _waitCommand,
imageCommand.Command,
systemCommand.Command,
}
diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go
index ac46ad5c6..1910b68b5 100644
--- a/cmd/podman/play_kube.go
+++ b/cmd/podman/play_kube.go
@@ -25,6 +25,11 @@ import (
"k8s.io/api/core/v1"
)
+const (
+ // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
+ createDirectoryPermission = 0755
+)
+
var (
playKubeCommand cliconfig.KubePlayValues
playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML"
@@ -144,12 +149,41 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
+ // map from name to mount point
+ volumes := make(map[string]string)
+ for _, volume := range podYAML.Spec.Volumes {
+ hostPath := volume.VolumeSource.HostPath
+ if hostPath == nil {
+ return errors.Errorf("HostPath is currently the only supported VolumeSource")
+ }
+ if hostPath.Type != nil {
+ switch *hostPath.Type {
+ case v1.HostPathDirectoryOrCreate:
+ if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) {
+ if err := os.Mkdir(hostPath.Path, createDirectoryPermission); err != nil {
+ return errors.Errorf("Error creating HostPath %s at %s", volume.Name, hostPath.Path)
+ }
+ }
+ case v1.HostPathDirectory:
+ // do nothing here because we will verify the path exists in validateVolumeHostDir
+ break
+ default:
+ return errors.Errorf("Directories are the only supported HostPath type")
+ }
+ }
+ if err := validateVolumeHostDir(hostPath.Path); err != nil {
+ return errors.Wrapf(err, "Error in parsing HostPath in YAML")
+ }
+ fmt.Println(volume.Name)
+ volumes[volume.Name] = hostPath.Path
+ }
+
for _, container := range podYAML.Spec.Containers {
newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil)
if err != nil {
return err
}
- createConfig := kubeContainerToCreateConfig(container, runtime, newImage, namespaces)
+ createConfig, err := kubeContainerToCreateConfig(container, runtime, newImage, namespaces, volumes)
if err != nil {
return err
}
@@ -194,7 +228,7 @@ func getPodPorts(containers []v1.Container) []ocicni.PortMapping {
}
// kubeContainerToCreateConfig takes a v1.Container and returns a createconfig describing a container
-func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Runtime, newImage *image2.Image, namespaces map[string]string) *createconfig.CreateConfig {
+func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Runtime, newImage *image2.Image, namespaces map[string]string, volumes map[string]string) (*createconfig.CreateConfig, error) {
var (
containerConfig createconfig.CreateConfig
envs map[string]string
@@ -239,6 +273,17 @@ func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Run
for _, e := range containerYAML.Env {
envs[e.Name] = e.Value
}
+
+ for _, volume := range containerYAML.VolumeMounts {
+ host_path, exists := volumes[volume.Name]
+ if !exists {
+ return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
+ }
+ if err := validateVolumeCtrDir(volume.MountPath); err != nil {
+ return nil, errors.Wrapf(err, "error in parsing MountPath")
+ }
+ containerConfig.Volumes = append(containerConfig.Volumes, fmt.Sprintf("%s:%s", host_path, volume.MountPath))
+ }
containerConfig.Env = envs
- return &containerConfig
+ return &containerConfig, nil
}
diff --git a/cmd/podman/pod.go b/cmd/podman/pod.go
index c1350bd4d..7067f2429 100644
--- a/cmd/podman/pod.go
+++ b/cmd/podman/pod.go
@@ -29,12 +29,13 @@ var podSubCommands = []*cobra.Command{
_podRestartCommand,
_podRmCommand,
_podStartCommand,
+ _podStatsCommand,
_podStopCommand,
+ _podTopCommand,
_podUnpauseCommand,
}
func init() {
podCommand.AddCommand(podSubCommands...)
- podCommand.AddCommand(getPodSubCommands()...)
podCommand.SetUsageTemplate(UsageTemplate())
}
diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go
index f5edd21f8..2761ce9cc 100644
--- a/cmd/podman/pod_stats.go
+++ b/cmd/podman/pod_stats.go
@@ -13,8 +13,8 @@ import (
tm "github.com/buger/goterm"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/ulule/deepcopier"
@@ -51,10 +51,6 @@ func init() {
}
func podStatsCmd(c *cliconfig.PodStatsValues) error {
- var (
- podFunc func() ([]*libpod.Pod, error)
- )
-
format := c.Format
all := c.All
latest := c.Latest
@@ -76,7 +72,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
all = true
}
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@@ -87,29 +83,12 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
times = 1
}
- if len(c.InputArgs) > 0 {
- podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.InputArgs, runtime) }
- } else if latest {
- podFunc = func() ([]*libpod.Pod, error) {
- latestPod, err := runtime.GetLatestPod()
- if err != nil {
- return nil, err
- }
- return []*libpod.Pod{latestPod}, err
- }
- } else if all {
- podFunc = runtime.GetAllPods
- } else {
- podFunc = runtime.GetRunningPods
- }
-
- pods, err := podFunc()
+ pods, err := runtime.GetStatPods(c)
if err != nil {
return errors.Wrapf(err, "unable to get a list of pods")
}
-
// First we need to get an initial pass of pod/ctr stats (these are not printed)
- var podStats []*libpod.PodContainerStats
+ var podStats []*adapter.PodContainerStats
for _, p := range pods {
cons, err := p.AllContainersByID()
if err != nil {
@@ -120,7 +99,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
for _, c := range cons {
emptyStats[c] = &libpod.ContainerStats{}
}
- ps := libpod.PodContainerStats{
+ ps := adapter.PodContainerStats{
Pod: p,
ContainerStats: emptyStats,
}
@@ -128,10 +107,10 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
}
// Create empty container stat results for our first pass
- var previousPodStats []*libpod.PodContainerStats
+ var previousPodStats []*adapter.PodContainerStats
for _, p := range pods {
cs := make(map[string]*libpod.ContainerStats)
- pcs := libpod.PodContainerStats{
+ pcs := adapter.PodContainerStats{
Pod: p,
ContainerStats: cs,
}
@@ -164,7 +143,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
}
for i := 0; i < times; i += step {
- var newStats []*libpod.PodContainerStats
+ var newStats []*adapter.PodContainerStats
for _, p := range pods {
prevStat := getPreviousPodContainerStats(p.ID(), previousPodStats)
newPodStats, err := p.GetPodStats(prevStat)
@@ -174,7 +153,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
if err != nil {
return err
}
- newPod := libpod.PodContainerStats{
+ newPod := adapter.PodContainerStats{
Pod: p,
ContainerStats: newPodStats,
}
@@ -202,7 +181,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
time.Sleep(time.Second)
previousPodStats := new([]*libpod.PodContainerStats)
deepcopier.Copy(newStats).To(previousPodStats)
- pods, err = podFunc()
+ pods, err = runtime.GetStatPods(c)
if err != nil {
return err
}
@@ -211,7 +190,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
return nil
}
-func podContainerStatsToPodStatOut(stats []*libpod.PodContainerStats) []*podStatOut {
+func podContainerStatsToPodStatOut(stats []*adapter.PodContainerStats) []*podStatOut {
var out []*podStatOut
for _, p := range stats {
for _, c := range p.ContainerStats {
@@ -295,7 +274,7 @@ func outputToStdOut(stats []*podStatOut) {
w.Flush()
}
-func getPreviousPodContainerStats(podID string, prev []*libpod.PodContainerStats) map[string]*libpod.ContainerStats {
+func getPreviousPodContainerStats(podID string, prev []*adapter.PodContainerStats) map[string]*libpod.ContainerStats {
for _, p := range prev {
if podID == p.Pod.ID() {
return p.ContainerStats
@@ -304,7 +283,7 @@ func getPreviousPodContainerStats(podID string, prev []*libpod.PodContainerStats
return map[string]*libpod.ContainerStats{}
}
-func outputJson(stats []*libpod.PodContainerStats) error {
+func outputJson(stats []*adapter.PodContainerStats) error {
b, err := json.MarshalIndent(&stats, "", " ")
if err != nil {
return err
diff --git a/cmd/podman/pod_top.go b/cmd/podman/pod_top.go
index 6a26e3dff..c5383d376 100644
--- a/cmd/podman/pod_top.go
+++ b/cmd/podman/pod_top.go
@@ -2,13 +2,12 @@ package main
import (
"fmt"
+ "github.com/containers/libpod/pkg/adapter"
"os"
"strings"
"text/tabwriter"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -50,8 +49,9 @@ func init() {
}
func podTopCmd(c *cliconfig.PodTopValues) error {
- var pod *libpod.Pod
- var err error
+ var (
+ descriptors []string
+ )
args := c.InputArgs
if c.ListDescriptors {
@@ -67,39 +67,22 @@ func podTopCmd(c *cliconfig.PodTopValues) error {
return errors.Errorf("you must provide the name or id of a running pod")
}
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
- var descriptors []string
if c.Latest {
descriptors = args
- pod, err = runtime.GetLatestPod()
} else {
descriptors = args[1:]
- pod, err = runtime.LookupPod(args[0])
}
-
- if err != nil {
- return errors.Wrapf(err, "unable to lookup requested container")
- }
-
- podStatus, err := shared.GetPodStatus(pod)
- if err != nil {
- return err
- }
- if podStatus != "Running" {
- return errors.Errorf("pod top can only be used on pods with at least one running container")
- }
-
- psOutput, err := pod.GetPodPidInformation(descriptors)
+ w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
+ psOutput, err := runtime.PodTop(c, descriptors)
if err != nil {
return err
}
-
- w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
for _, proc := range psOutput {
fmt.Fprintln(w, proc)
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 73e6c15f9..6109bd290 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -549,6 +549,10 @@ method ExportContainer(name: string, path: string) -> (tarfile: string)
# ~~~
method GetContainerStats(name: string) -> (container: ContainerStats)
+# GetContainerStatsWithHistory takes a previous set of container statistics and uses libpod functions
+# to calculate the containers statistics based on current and previous measurements.
+method GetContainerStatsWithHistory(previousStats: ContainerStats) -> (container: ContainerStats)
+
# This method has not be implemented yet.
# method ResizeContainerTty() -> (notimplemented: NotImplemented)
@@ -617,10 +621,10 @@ method UnpauseContainer(name: string) -> (container: string)
# ~~~
method GetAttachSockets(name: string) -> (sockets: Sockets)
-# WaitContainer takes the name or ID of a container and waits until the container stops. Upon stopping, the return
-# code of the container is returned. If the container container cannot be found by ID or name,
-# a [ContainerNotFound](#ContainerNotFound) error is returned.
-method WaitContainer(name: string) -> (exitcode: int)
+# WaitContainer takes the name or ID of a container and waits the given interval in milliseconds until the container
+# stops. Upon stopping, the return code of the container is returned. If the container container cannot be found by ID
+# or name, a [ContainerNotFound](#ContainerNotFound) error is returned.
+method WaitContainer(name: string, interval: int) -> (exitcode: int)
# RemoveContainer requires the name or ID of container as well a boolean representing whether a running container can be stopped and removed, and a boolean
# indicating whether to remove builtin volumes. Upon successful removal of the
@@ -952,8 +956,7 @@ method RemovePod(name: string, force: bool) -> (pod: string)
# This method has not be implemented yet.
# method WaitPod() -> (notimplemented: NotImplemented)
-# This method has not been implemented yet.
-# method TopPod() -> (notimplemented: NotImplemented)
+method TopPod(pod: string, latest: bool, descriptors: []string) -> (stats: []string)
# GetPodStats takes the name or ID of a pod and returns a pod name and slice of ContainerStats structure which
# contains attributes like memory and cpu usage. If the pod cannot be found, a [PodNotFound](#PodNotFound)
diff --git a/cmd/podman/wait.go b/cmd/podman/wait.go
index 9df2e3208..6c2a8c9ff 100644
--- a/cmd/podman/wait.go
+++ b/cmd/podman/wait.go
@@ -2,11 +2,11 @@ package main
import (
"fmt"
- "os"
+ "reflect"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -49,43 +49,36 @@ func waitCmd(c *cliconfig.WaitValues) error {
return errors.Errorf("you must provide at least one container name or id")
}
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ if c.Interval == 0 {
+ return errors.Errorf("interval must be greater then 0")
+ }
+ interval := time.Duration(c.Interval) * time.Millisecond
+
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
- return errors.Wrapf(err, "error creating libpod runtime")
+ return errors.Wrapf(err, "error creating runtime")
}
defer runtime.Shutdown(false)
+ ok, failures, err := runtime.WaitOnContainers(getContext(), c, interval)
if err != nil {
- return errors.Wrapf(err, "could not get config")
+ return err
}
- var lastError error
- if c.Latest {
- latestCtr, err := runtime.GetLatestContainer()
- if err != nil {
- return errors.Wrapf(err, "unable to wait on latest container")
- }
- args = append(args, latestCtr.ID())
+ for _, id := range ok {
+ fmt.Println(id)
}
- for _, container := range args {
- ctr, err := runtime.LookupContainer(container)
- if err != nil {
- return errors.Wrapf(err, "unable to find container %s", container)
- }
- if c.Interval == 0 {
- return errors.Errorf("interval must be greater then 0")
- }
- returnCode, err := ctr.WaitWithInterval(time.Duration(c.Interval) * time.Millisecond)
- if err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
- }
- lastError = errors.Wrapf(err, "failed to wait for the container %v", container)
- } else {
- fmt.Println(returnCode)
+ if len(failures) > 0 {
+ keys := reflect.ValueOf(failures).MapKeys()
+ lastKey := keys[len(keys)-1].String()
+ lastErr := failures[lastKey]
+ delete(failures, lastKey)
+
+ for _, err := range failures {
+ outputError(err)
}
+ return lastErr
}
-
- return lastError
+ return nil
}