From 4bf973a9f61eae3b02925a42ccfa784baeb917dc Mon Sep 17 00:00:00 2001 From: baude Date: Fri, 22 Feb 2019 11:07:18 -0600 Subject: Enable more podman-remote pod commands enable pod start, stop, and kill subcommands for the remote-client. Signed-off-by: baude --- cmd/podman/build.go | 2 +- cmd/podman/commands.go | 3 - cmd/podman/containers_prune.go | 2 +- cmd/podman/exists.go | 2 +- cmd/podman/export.go | 2 +- cmd/podman/history.go | 2 +- cmd/podman/imagefilters/filters.go | 2 +- cmd/podman/images.go | 2 +- cmd/podman/images_prune.go | 2 +- cmd/podman/import.go | 2 +- cmd/podman/info.go | 2 +- cmd/podman/inspect.go | 2 +- cmd/podman/load.go | 2 +- cmd/podman/pod.go | 3 + cmd/podman/pod_inspect.go | 2 +- cmd/podman/pod_kill.go | 40 +- cmd/podman/pod_rm.go | 2 +- cmd/podman/pod_start.go | 42 +- cmd/podman/pod_stop.go | 47 +- cmd/podman/pull.go | 2 +- cmd/podman/push.go | 2 +- cmd/podman/rmi.go | 2 +- cmd/podman/save.go | 7 +- cmd/podman/system_prune.go | 2 +- cmd/podman/tag.go | 2 +- cmd/podman/volume_create.go | 2 +- cmd/podman/volume_inspect.go | 2 +- cmd/podman/volume_ls.go | 2 +- cmd/podman/volume_prune.go | 2 +- cmd/podman/volume_rm.go | 2 +- libpod/adapter/client.go | 47 -- libpod/adapter/containers_remote.go | 50 --- libpod/adapter/images_remote.go | 24 - libpod/adapter/info_remote.go | 56 --- libpod/adapter/pods.go | 54 --- libpod/adapter/pods_remote.go | 98 ----- libpod/adapter/runtime.go | 335 -------------- libpod/adapter/runtime_remote.go | 798 ---------------------------------- libpod/adapter/shortcuts/shortcuts.go | 27 -- libpod/adapter/volumes_remote.go | 33 -- pkg/adapter/client.go | 47 ++ pkg/adapter/containers_remote.go | 50 +++ pkg/adapter/images_remote.go | 24 + pkg/adapter/info_remote.go | 56 +++ pkg/adapter/pods.go | 152 +++++++ pkg/adapter/pods_remote.go | 170 ++++++++ pkg/adapter/runtime.go | 335 ++++++++++++++ pkg/adapter/runtime_remote.go | 798 ++++++++++++++++++++++++++++++++++ pkg/adapter/shortcuts/shortcuts.go | 27 ++ pkg/adapter/volumes_remote.go | 33 ++ pkg/varlinkapi/pods.go | 2 +- test/e2e/pod_start_test.go | 1 - test/e2e/pod_stop_test.go | 1 - 53 files changed, 1769 insertions(+), 1639 deletions(-) delete mode 100644 libpod/adapter/client.go delete mode 100644 libpod/adapter/containers_remote.go delete mode 100644 libpod/adapter/images_remote.go delete mode 100644 libpod/adapter/info_remote.go delete mode 100644 libpod/adapter/pods.go delete mode 100644 libpod/adapter/pods_remote.go delete mode 100644 libpod/adapter/runtime.go delete mode 100644 libpod/adapter/runtime_remote.go delete mode 100644 libpod/adapter/shortcuts/shortcuts.go delete mode 100644 libpod/adapter/volumes_remote.go create mode 100644 pkg/adapter/client.go create mode 100644 pkg/adapter/containers_remote.go create mode 100644 pkg/adapter/images_remote.go create mode 100644 pkg/adapter/info_remote.go create mode 100644 pkg/adapter/pods.go create mode 100644 pkg/adapter/pods_remote.go create mode 100644 pkg/adapter/runtime.go create mode 100644 pkg/adapter/runtime_remote.go create mode 100644 pkg/adapter/shortcuts/shortcuts.go create mode 100644 pkg/adapter/volumes_remote.go diff --git a/cmd/podman/build.go b/cmd/podman/build.go index bb252f171..34fe6a012 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -9,7 +9,7 @@ import ( "github.com/containers/buildah/imagebuildah" buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/docker/go-units" "github.com/pkg/errors" "github.com/sirupsen/logrus" diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index d8fc44c2f..310ec8378 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -94,13 +94,10 @@ func getContainerSubCommands() []*cobra.Command { func getPodSubCommands() []*cobra.Command { return []*cobra.Command{ _podCreateCommand, - _podKillCommand, _podPauseCommand, _podPsCommand, _podRestartCommand, - _podStartCommand, _podStatsCommand, - _podStopCommand, _podTopCommand, _podUnpauseCommand, } diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go index bae578e1d..6e4960429 100644 --- a/cmd/podman/containers_prune.go +++ b/cmd/podman/containers_prune.go @@ -6,7 +6,7 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cmd/podman/exists.go b/cmd/podman/exists.go index aad203818..74a4c841b 100644 --- a/cmd/podman/exists.go +++ b/cmd/podman/exists.go @@ -6,8 +6,8 @@ import ( "os" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" ) diff --git a/cmd/podman/export.go b/cmd/podman/export.go index a593a4753..5873bad3d 100644 --- a/cmd/podman/export.go +++ b/cmd/podman/export.go @@ -4,7 +4,7 @@ import ( "os" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/sirupsen/logrus" diff --git a/cmd/podman/history.go b/cmd/podman/history.go index 6791257d9..103ef08e8 100644 --- a/cmd/podman/history.go +++ b/cmd/podman/history.go @@ -8,8 +8,8 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/formats" - "github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/adapter" "github.com/docker/go-units" "github.com/pkg/errors" "github.com/spf13/cobra" diff --git a/cmd/podman/imagefilters/filters.go b/cmd/podman/imagefilters/filters.go index 366510202..d01eb7436 100644 --- a/cmd/podman/imagefilters/filters.go +++ b/cmd/podman/imagefilters/filters.go @@ -5,7 +5,7 @@ import ( "strings" "time" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/inspect" ) diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 56810eaeb..6e82195a9 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -11,8 +11,8 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/imagefilters" - "github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/adapter" "github.com/docker/go-units" "github.com/opencontainers/go-digest" "github.com/pkg/errors" diff --git a/cmd/podman/images_prune.go b/cmd/podman/images_prune.go index cc0dcb99a..79dcd097c 100644 --- a/cmd/podman/images_prune.go +++ b/cmd/podman/images_prune.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/import.go b/cmd/podman/import.go index 053408ff3..a64b03d6d 100644 --- a/cmd/podman/import.go +++ b/cmd/podman/import.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/info.go b/cmd/podman/info.go index 06dbbd748..a1473dac9 100644 --- a/cmd/podman/info.go +++ b/cmd/podman/info.go @@ -7,7 +7,7 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/version" "github.com/pkg/errors" "github.com/spf13/cobra" diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index 48b953207..46883b31d 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -8,7 +8,7 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/shared" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" cc "github.com/containers/libpod/pkg/spec" "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" diff --git a/cmd/podman/load.go b/cmd/podman/load.go index 514c9f1e9..272cd78d2 100644 --- a/cmd/podman/load.go +++ b/cmd/podman/load.go @@ -7,7 +7,7 @@ import ( "os" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/pod.go b/cmd/podman/pod.go index d65e0b384..4c7c416ce 100644 --- a/cmd/podman/pod.go +++ b/cmd/podman/pod.go @@ -22,7 +22,10 @@ var podCommand = cliconfig.PodmanCommand{ var podSubCommands = []*cobra.Command{ _podExistsCommand, _podInspectCommand, + _podKillCommand, _podRmCommand, + _podStartCommand, + _podStopCommand, } func init() { diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go index 1f4d1a3dd..5a32b5c5d 100644 --- a/cmd/podman/pod_inspect.go +++ b/cmd/podman/pod_inspect.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/pod_kill.go b/cmd/podman/pod_kill.go index d0318b409..aaaae0f7d 100644 --- a/cmd/podman/pod_kill.go +++ b/cmd/podman/pod_kill.go @@ -5,7 +5,7 @@ import ( "syscall" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/pkg/adapter" "github.com/docker/docker/pkg/signal" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -45,7 +45,7 @@ func init() { // podKillCmd kills one or more pods with a signal func podKillCmd(c *cliconfig.PodKillValues) error { - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } @@ -63,30 +63,20 @@ func podKillCmd(c *cliconfig.PodKillValues) error { killSignal = uint(sysSignal) } - // getPodsFromContext returns an error when a requested pod - // isn't found. The only fatal error scenerio is when there are no pods - // in which case the following loop will be skipped. - pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime) + podKillIds, podKillErrors := runtime.KillPods(getContext(), c, killSignal) + for _, p := range podKillIds { + fmt.Println(p) + } + if len(podKillErrors) == 0 { + return nil + } + // Grab the last error + lastError := podKillErrors[len(podKillErrors)-1] + // Remove the last error from the error slice + podKillErrors = podKillErrors[:len(podKillErrors)-1] - for _, pod := range pods { - ctr_errs, err := pod.Kill(killSignal) - if ctr_errs != nil { - for ctr, err := range ctr_errs { - if lastError != nil { - logrus.Errorf("%q", lastError) - } - lastError = errors.Wrapf(err, "unable to kill container %q in pod %q", ctr, pod.ID()) - } - continue - } - if err != nil { - if lastError != nil { - logrus.Errorf("%q", lastError) - } - lastError = errors.Wrapf(err, "unable to kill pod %q", pod.ID()) - continue - } - fmt.Println(pod.ID()) + for _, err := range podKillErrors { + logrus.Errorf("%q", err) } return lastError } diff --git a/cmd/podman/pod_rm.go b/cmd/podman/pod_rm.go index b552b9f42..ba16d03c7 100644 --- a/cmd/podman/pod_rm.go +++ b/cmd/podman/pod_rm.go @@ -2,9 +2,9 @@ package main import ( "fmt" - "github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cmd/podman/pod_start.go b/cmd/podman/pod_start.go index 3bba5c2e9..5761afd52 100644 --- a/cmd/podman/pod_start.go +++ b/cmd/podman/pod_start.go @@ -4,7 +4,7 @@ import ( "fmt" "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/sirupsen/logrus" "github.com/spf13/cobra" @@ -45,38 +45,26 @@ func init() { } func podStartCmd(c *cliconfig.PodStartValues) error { - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) - // getPodsFromContext returns an error when a requested pod - // isn't found. The only fatal error scenerio is when there are no pods - // in which case the following loop will be skipped. - pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime) - - ctx := getContext() - for _, pod := range pods { - ctr_errs, err := pod.Start(ctx) - if ctr_errs != nil { - for ctr, err := range ctr_errs { - if lastError != nil { - logrus.Errorf("%q", lastError) - } - lastError = errors.Wrapf(err, "unable to start container %q on pod %q", ctr, pod.ID()) - } - continue - } - if err != nil { - if lastError != nil { - logrus.Errorf("%q", lastError) - } - lastError = errors.Wrapf(err, "unable to start pod %q", pod.ID()) - continue - } - fmt.Println(pod.ID()) + podStartIDs, podStartErrors := runtime.StartPods(getContext(), c) + for _, p := range podStartIDs { + fmt.Println(p) + } + if len(podStartErrors) == 0 { + return nil } + // Grab the last error + lastError := podStartErrors[len(podStartErrors)-1] + // Remove the last error from the error slice + podStartErrors = podStartErrors[:len(podStartErrors)-1] + for _, err := range podStartErrors { + logrus.Errorf("%q", err) + } return lastError } diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go index 52c92b521..62d0d4aa5 100644 --- a/cmd/podman/pod_stop.go +++ b/cmd/podman/pod_stop.go @@ -4,7 +4,7 @@ import ( "fmt" "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/sirupsen/logrus" "github.com/spf13/cobra" @@ -47,43 +47,26 @@ func init() { } func podStopCmd(c *cliconfig.PodStopValues) error { - timeout := -1 - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) - // getPodsFromContext returns an error when a requested pod - // isn't found. The only fatal error scenerio is when there are no pods - // in which case the following loop will be skipped. - pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime) - - ctx := getContext() - - if c.Flag("timeout").Changed { - timeout = int(c.Timeout) + podStopIds, podStopErrors := runtime.StopPods(getContext(), c) + for _, p := range podStopIds { + fmt.Println(p) } - for _, pod := range pods { - // set cleanup to true to clean mounts and namespaces - ctr_errs, err := pod.StopWithTimeout(ctx, true, timeout) - if ctr_errs != nil { - for ctr, err := range ctr_errs { - if lastError != nil { - logrus.Errorf("%q", lastError) - } - lastError = errors.Wrapf(err, "unable to stop container %q on pod %q", ctr, pod.ID()) - } - continue - } - if err != nil { - if lastError != nil { - logrus.Errorf("%q", lastError) - } - lastError = errors.Wrapf(err, "unable to stop pod %q", pod.ID()) - continue - } - fmt.Println(pod.ID()) + if len(podStopErrors) == 0 { + return nil + } + // Grab the last error + lastError := podStopErrors[len(podStopErrors)-1] + // Remove the last error from the error slice + podStopErrors = podStopErrors[:len(podStopErrors)-1] + + for _, err := range podStopErrors { + logrus.Errorf("%q", err) } return lastError } diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go index 476bccb0e..71f555162 100644 --- a/cmd/podman/pull.go +++ b/cmd/podman/pull.go @@ -11,9 +11,9 @@ import ( "github.com/containers/image/transports/alltransports" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/common" image2 "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/util" opentracing "github.com/opentracing/opentracing-go" "github.com/pkg/errors" diff --git a/cmd/podman/push.go b/cmd/podman/push.go index 881d8cebc..56261a8d3 100644 --- a/cmd/podman/push.go +++ b/cmd/podman/push.go @@ -10,8 +10,8 @@ import ( "github.com/containers/image/manifest" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/util" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go index fb27772f5..fbaa19336 100644 --- a/cmd/podman/rmi.go +++ b/cmd/podman/rmi.go @@ -5,7 +5,7 @@ import ( "os" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/storage" "github.com/pkg/errors" "github.com/spf13/cobra" diff --git a/cmd/podman/save.go b/cmd/podman/save.go index ab421add6..161540deb 100644 --- a/cmd/podman/save.go +++ b/cmd/podman/save.go @@ -1,14 +1,15 @@ package main import ( + "os" + "strings" + "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "os" - "strings" ) const ( diff --git a/cmd/podman/system_prune.go b/cmd/podman/system_prune.go index a91d7bf0a..a823dcad1 100644 --- a/cmd/podman/system_prune.go +++ b/cmd/podman/system_prune.go @@ -8,7 +8,7 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cmd/podman/tag.go b/cmd/podman/tag.go index 422e9dbf6..2b9d67066 100644 --- a/cmd/podman/tag.go +++ b/cmd/podman/tag.go @@ -2,7 +2,7 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/volume_create.go b/cmd/podman/volume_create.go index 6c8a78922..833191082 100644 --- a/cmd/podman/volume_create.go +++ b/cmd/podman/volume_create.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/volume_inspect.go b/cmd/podman/volume_inspect.go index 3b4ba51d5..dc6afbc36 100644 --- a/cmd/podman/volume_inspect.go +++ b/cmd/podman/volume_inspect.go @@ -2,7 +2,7 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/volume_ls.go b/cmd/podman/volume_ls.go index 0edadc5ac..5adfc1e91 100644 --- a/cmd/podman/volume_ls.go +++ b/cmd/podman/volume_ls.go @@ -6,7 +6,7 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/formats" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/volume_prune.go b/cmd/podman/volume_prune.go index a2205140f..1f7931aa4 100644 --- a/cmd/podman/volume_prune.go +++ b/cmd/podman/volume_prune.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cmd/podman/volume_rm.go b/cmd/podman/volume_rm.go index 14847a949..03b6ccae1 100644 --- a/cmd/podman/volume_rm.go +++ b/cmd/podman/volume_rm.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/adapter" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/libpod/adapter/client.go b/libpod/adapter/client.go deleted file mode 100644 index 6512a5952..000000000 --- a/libpod/adapter/client.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build remoteclient - -package adapter - -import ( - "os" - - "github.com/sirupsen/logrus" - "github.com/varlink/go/varlink" -) - -// DefaultAddress is the default address of the varlink socket -const DefaultAddress = "unix:/run/podman/io.podman" - -// Connect provides a varlink connection -func (r RemoteRuntime) Connect() (*varlink.Connection, error) { - var err error - var connection *varlink.Connection - if bridge := os.Getenv("PODMAN_VARLINK_BRIDGE"); bridge != "" { - logrus.Infof("Connecting with varlink bridge") - logrus.Debugf("%s", bridge) - connection, err = varlink.NewBridge(bridge) - } else { - address := os.Getenv("PODMAN_VARLINK_ADDRESS") - if address == "" { - address = DefaultAddress - } - logrus.Infof("Connecting with varlink address") - logrus.Debugf("%s", address) - connection, err = varlink.NewConnection(address) - } - if err != nil { - return nil, err - } - return connection, nil -} - -// RefreshConnection is used to replace the current r.Conn after things like -// using an upgraded varlink connection -func (r RemoteRuntime) RefreshConnection() error { - newConn, err := r.Connect() - if err != nil { - return err - } - r.Conn = newConn - return nil -} diff --git a/libpod/adapter/containers_remote.go b/libpod/adapter/containers_remote.go deleted file mode 100644 index 9623304e5..000000000 --- a/libpod/adapter/containers_remote.go +++ /dev/null @@ -1,50 +0,0 @@ -// +build remoteclient - -package adapter - -import ( - "encoding/json" - - iopodman "github.com/containers/libpod/cmd/podman/varlink" - "github.com/containers/libpod/libpod" - "github.com/containers/libpod/pkg/inspect" -) - -// Inspect returns an inspect struct from varlink -func (c *Container) Inspect(size bool) (*inspect.ContainerInspectData, error) { - reply, err := iopodman.ContainerInspectData().Call(c.Runtime.Conn, c.ID()) - if err != nil { - return nil, err - } - data := inspect.ContainerInspectData{} - if err := json.Unmarshal([]byte(reply), &data); err != nil { - return nil, err - } - return &data, err -} - -// ID returns the ID of the container -func (c *Container) ID() string { - return c.config.ID -} - -// GetArtifact returns a container's artifacts -func (c *Container) GetArtifact(name string) ([]byte, error) { - var data []byte - reply, err := iopodman.ContainerArtifacts().Call(c.Runtime.Conn, c.ID(), name) - if err != nil { - return nil, err - } - if err := json.Unmarshal([]byte(reply), &data); err != nil { - return nil, err - } - return data, err -} - -// Config returns a container's Config ... same as ctr.Config() -func (c *Container) Config() *libpod.ContainerConfig { - if c.config != nil { - return c.config - } - return c.Runtime.Config(c.ID()) -} diff --git a/libpod/adapter/images_remote.go b/libpod/adapter/images_remote.go deleted file mode 100644 index e7b38dccc..000000000 --- a/libpod/adapter/images_remote.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build remoteclient - -package adapter - -import ( - "context" - "encoding/json" - - iopodman "github.com/containers/libpod/cmd/podman/varlink" - "github.com/containers/libpod/pkg/inspect" -) - -// Inspect returns returns an ImageData struct from over a varlink connection -func (i *ContainerImage) Inspect(ctx context.Context) (*inspect.ImageData, error) { - reply, err := iopodman.InspectImage().Call(i.Runtime.Conn, i.ID()) - if err != nil { - return nil, err - } - data := inspect.ImageData{} - if err := json.Unmarshal([]byte(reply), &data); err != nil { - return nil, err - } - return &data, nil -} diff --git a/libpod/adapter/info_remote.go b/libpod/adapter/info_remote.go deleted file mode 100644 index 3b691ed17..000000000 --- a/libpod/adapter/info_remote.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build remoteclient - -package adapter - -import ( - "encoding/json" - - "github.com/containers/libpod/cmd/podman/varlink" - "github.com/containers/libpod/libpod" -) - -// Info returns information for the host system and its components -func (r RemoteRuntime) Info() ([]libpod.InfoData, error) { - // TODO the varlink implementation for info should be updated to match the output for regular info - var ( - reply []libpod.InfoData - hostInfo map[string]interface{} - store map[string]interface{} - ) - - registries := make(map[string]interface{}) - insecureRegistries := make(map[string]interface{}) - conn, err := r.Connect() - if err != nil { - return nil, err - } - defer conn.Close() - info, err := iopodman.GetInfo().Call(conn) - if err != nil { - return nil, err - } - - // info.host -> map[string]interface{} - h, err := json.Marshal(info.Host) - if err != nil { - return nil, err - } - json.Unmarshal(h, &hostInfo) - - // info.store -> map[string]interface{} - s, err := json.Marshal(info.Store) - if err != nil { - return nil, err - } - json.Unmarshal(s, &store) - - registries["registries"] = info.Registries - insecureRegistries["registries"] = info.Insecure_registries - - // Add everything to the reply - reply = append(reply, libpod.InfoData{Type: "host", Data: hostInfo}) - reply = append(reply, libpod.InfoData{Type: "registries", Data: registries}) - reply = append(reply, libpod.InfoData{Type: "insecure registries", Data: insecureRegistries}) - reply = append(reply, libpod.InfoData{Type: "store", Data: store}) - return reply, nil -} diff --git a/libpod/adapter/pods.go b/libpod/adapter/pods.go deleted file mode 100644 index 9841c20c0..000000000 --- a/libpod/adapter/pods.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build !remoteclient - -package adapter - -import ( - "context" - "github.com/containers/libpod/libpod/adapter/shortcuts" - - "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod" -) - -// Pod ... -type Pod struct { - *libpod.Pod -} - -// RemovePods ... -func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) { - var ( - errs []error - podids []string - ) - pods, err := shortcuts.GetPodsByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) - if err != nil { - errs = append(errs, err) - return nil, errs - } - - for _, p := range pods { - if err := r.RemovePod(ctx, p, cli.Force, cli.Force); err != nil { - errs = append(errs, err) - } else { - podids = append(podids, p.ID()) - } - } - return podids, errs -} - -// GetLatestPod gets the latest pod and wraps it in an adapter pod -func (r *LocalRuntime) GetLatestPod() (*Pod, error) { - pod := Pod{} - p, err := r.Runtime.GetLatestPod() - pod.Pod = p - return &pod, err -} - -// LookupPod gets a pod by name or id and wraps it in an adapter pod -func (r *LocalRuntime) LookupPod(nameOrID string) (*Pod, error) { - pod := Pod{} - p, err := r.Runtime.LookupPod(nameOrID) - pod.Pod = p - return &pod, err -} diff --git a/libpod/adapter/pods_remote.go b/libpod/adapter/pods_remote.go deleted file mode 100644 index 57c78821f..000000000 --- a/libpod/adapter/pods_remote.go +++ /dev/null @@ -1,98 +0,0 @@ -// +build remoteclient - -package adapter - -import ( - "context" - "encoding/json" - - "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/varlink" - "github.com/containers/libpod/libpod" - "github.com/pkg/errors" - "github.com/ulule/deepcopier" -) - -// Pod ... -type Pod struct { - remotepod -} - -type remotepod struct { - config *libpod.PodConfig - state *libpod.PodInspectState - containers []libpod.PodContainerInfo - Runtime *LocalRuntime -} - -// RemovePods removes one or more based on the cli context. -func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) { - var ( - rmErrs []error - rmPods []string - ) - podIDs, err := iopodman.GetPodsByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs) - if err != nil { - rmErrs = append(rmErrs, err) - return nil, rmErrs - } - - for _, p := range podIDs { - reply, err := iopodman.RemovePod().Call(r.Conn, p, cli.Force) - if err != nil { - rmErrs = append(rmErrs, err) - } else { - rmPods = append(rmPods, reply) - } - } - return rmPods, rmErrs -} - -// Inspect looks up a pod by name or id and embeds its data into a remote pod -// object. -func (r *LocalRuntime) Inspect(nameOrID string) (*Pod, error) { - reply, err := iopodman.PodStateData().Call(r.Conn, nameOrID) - if err != nil { - return nil, err - } - data := libpod.PodInspect{} - if err := json.Unmarshal([]byte(reply), &data); err != nil { - return nil, err - } - pod := Pod{} - pod.Runtime = r - pod.config = data.Config - pod.state = data.State - pod.containers = data.Containers - return &pod, nil -} - -// GetLatestPod gets the latest pod and wraps it in an adapter pod -func (r *LocalRuntime) GetLatestPod() (*Pod, error) { - reply, err := iopodman.GetPodsByContext().Call(r.Conn, false, true, nil) - if err != nil { - return nil, err - } - if len(reply) > 0 { - return r.Inspect(reply[0]) - } - return nil, errors.New("no pods exist") -} - -// LookupPod gets a pod by name or ID and wraps it in an adapter pod -func (r *LocalRuntime) LookupPod(nameOrID string) (*Pod, error) { - return r.Inspect(nameOrID) -} - -// Inspect, like libpod pod inspect, returns a libpod.PodInspect object from -// the data of a remotepod data struct -func (p *Pod) Inspect() (*libpod.PodInspect, error) { - config := new(libpod.PodConfig) - deepcopier.Copy(p.remotepod.config).To(config) - inspectData := libpod.PodInspect{ - Config: config, - State: p.remotepod.state, - Containers: p.containers, - } - return &inspectData, nil -} diff --git a/libpod/adapter/runtime.go b/libpod/adapter/runtime.go deleted file mode 100644 index 4f5b98dbb..000000000 --- a/libpod/adapter/runtime.go +++ /dev/null @@ -1,335 +0,0 @@ -// +build !remoteclient - -package adapter - -import ( - "context" - "io" - "io/ioutil" - "os" - "strconv" - - "github.com/containers/buildah" - "github.com/containers/buildah/imagebuildah" - "github.com/containers/buildah/pkg/parse" - "github.com/containers/image/docker/reference" - "github.com/containers/image/types" - "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/image" - "github.com/containers/libpod/pkg/rootless" - "github.com/pkg/errors" -) - -// LocalRuntime describes a typical libpod runtime -type LocalRuntime struct { - *libpod.Runtime - Remote bool -} - -// ContainerImage ... -type ContainerImage struct { - *image.Image -} - -// Container ... -type Container struct { - *libpod.Container -} - -// Volume ... -type Volume struct { - *libpod.Volume -} - -// VolumeFilter is for filtering volumes on the client -type VolumeFilter func(*Volume) bool - -// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it -func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) { - runtime, err := libpodruntime.GetRuntime(c) - if err != nil { - return nil, err - } - return &LocalRuntime{ - Runtime: runtime, - }, nil -} - -// GetImages returns a slice of images in containerimages -func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { - var containerImages []*ContainerImage - images, err := r.Runtime.ImageRuntime().GetImages() - if err != nil { - return nil, err - } - for _, i := range images { - containerImages = append(containerImages, &ContainerImage{i}) - } - return containerImages, nil - -} - -// NewImageFromLocal returns a containerimage representation of a image from local storage -func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { - img, err := r.Runtime.ImageRuntime().NewFromLocal(name) - if err != nil { - return nil, err - } - return &ContainerImage{img}, nil -} - -// LoadFromArchiveReference calls into local storage to load an image from an archive -func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) { - var containerImages []*ContainerImage - imgs, err := r.Runtime.ImageRuntime().LoadFromArchiveReference(ctx, srcRef, signaturePolicyPath, writer) - if err != nil { - return nil, err - } - for _, i := range imgs { - ci := ContainerImage{i} - containerImages = append(containerImages, &ci) - } - return containerImages, nil -} - -// New calls into local storage to look for an image in local storage or to pull it -func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool, label *string) (*ContainerImage, error) { - img, err := r.Runtime.ImageRuntime().New(ctx, name, signaturePolicyPath, authfile, writer, dockeroptions, signingoptions, forcePull, label) - if err != nil { - return nil, err - } - return &ContainerImage{img}, nil -} - -// RemoveImage calls into local storage and removes an image -func (r *LocalRuntime) RemoveImage(ctx context.Context, img *ContainerImage, force bool) (string, error) { - return r.Runtime.RemoveImage(ctx, img.Image, force) -} - -// LookupContainer ... -func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { - ctr, err := r.Runtime.LookupContainer(idOrName) - if err != nil { - return nil, err - } - return &Container{ctr}, nil -} - -// PruneImages is wrapper into PruneImages within the image pkg -func (r *LocalRuntime) PruneImages(all bool) ([]string, error) { - return r.ImageRuntime().PruneImages(all) -} - -// Export is a wrapper to container export to a tarfile -func (r *LocalRuntime) Export(name string, path string) error { - ctr, err := r.Runtime.LookupContainer(name) - if err != nil { - return errors.Wrapf(err, "error looking up container %q", name) - } - if os.Geteuid() != 0 { - state, err := ctr.State() - if err != nil { - return errors.Wrapf(err, "cannot read container state %q", ctr.ID()) - } - if state == libpod.ContainerStateRunning || state == libpod.ContainerStatePaused { - data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile) - if err != nil { - return errors.Wrapf(err, "cannot read conmon PID file %q", ctr.Config().ConmonPidFile) - } - conmonPid, err := strconv.Atoi(string(data)) - if err != nil { - return errors.Wrapf(err, "cannot parse PID %q", data) - } - became, ret, err := rootless.JoinDirectUserAndMountNS(uint(conmonPid)) - if err != nil { - return err - } - if became { - os.Exit(ret) - } - } else { - became, ret, err := rootless.BecomeRootInUserNS() - if err != nil { - return err - } - if became { - os.Exit(ret) - } - } - } - - return ctr.Export(path) -} - -// Import is a wrapper to import a container image -func (r *LocalRuntime) Import(ctx context.Context, source, reference string, changes []string, history string, quiet bool) (string, error) { - return r.Runtime.Import(ctx, source, reference, changes, history, quiet) -} - -// CreateVolume is a wrapper to create volumes -func (r *LocalRuntime) CreateVolume(ctx context.Context, c *cliconfig.VolumeCreateValues, labels, opts map[string]string) (string, error) { - var ( - options []libpod.VolumeCreateOption - volName string - ) - - if len(c.InputArgs) > 0 { - volName = c.InputArgs[0] - options = append(options, libpod.WithVolumeName(volName)) - } - - if c.Flag("driver").Changed { - options = append(options, libpod.WithVolumeDriver(c.Driver)) - } - - if len(labels) != 0 { - options = append(options, libpod.WithVolumeLabels(labels)) - } - - if len(options) != 0 { - options = append(options, libpod.WithVolumeOptions(opts)) - } - newVolume, err := r.NewVolume(ctx, options...) - if err != nil { - return "", err - } - return newVolume.Name(), nil -} - -// RemoveVolumes is a wrapper to remove volumes -func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmValues) ([]string, error) { - return r.Runtime.RemoveVolumes(ctx, c.InputArgs, c.All, c.Force) -} - -// Push is a wrapper to push an image to a registry -func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { - newImage, err := r.ImageRuntime().NewFromLocal(srcName) - if err != nil { - return err - } - return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil) -} - -// InspectVolumes returns a slice of volumes based on an arg list or --all -func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*Volume, error) { - var ( - volumes []*libpod.Volume - err error - ) - - if c.All { - volumes, err = r.GetAllVolumes() - } else { - for _, v := range c.InputArgs { - vol, err := r.GetVolume(v) - if err != nil { - return nil, err - } - volumes = append(volumes, vol) - } - } - if err != nil { - return nil, err - } - return libpodVolumeToVolume(volumes), nil -} - -// Volumes returns a slice of localruntime volumes -func (r *LocalRuntime) Volumes(ctx context.Context) ([]*Volume, error) { - vols, err := r.GetAllVolumes() - if err != nil { - return nil, err - } - return libpodVolumeToVolume(vols), nil -} - -// libpodVolumeToVolume converts a slice of libpod volumes to a slice -// of localruntime volumes (same as libpod) -func libpodVolumeToVolume(volumes []*libpod.Volume) []*Volume { - var vols []*Volume - for _, v := range volumes { - newVol := Volume{ - v, - } - vols = append(vols, &newVol) - } - return vols -} - -// Build is the wrapper to build images -func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) error { - namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command) - if err != nil { - return errors.Wrapf(err, "error parsing namespace-related options") - } - usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command) - if err != nil { - return errors.Wrapf(err, "error parsing ID mapping options") - } - namespaceOptions.AddOrReplace(usernsOption...) - - systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command) - if err != nil { - return errors.Wrapf(err, "error building system context") - } - - authfile := c.Authfile - if len(c.Authfile) == 0 { - authfile = os.Getenv("REGISTRY_AUTH_FILE") - } - - systemContext.AuthFilePath = authfile - commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command) - if err != nil { - return err - } - - options.NamespaceOptions = namespaceOptions - options.ConfigureNetwork = networkPolicy - options.IDMappingOptions = idmappingOptions - options.CommonBuildOpts = commonOpts - options.SystemContext = systemContext - - if c.Flag("runtime").Changed { - options.Runtime = r.GetOCIRuntimePath() - } - if c.Quiet { - options.ReportWriter = ioutil.Discard - } - - if rootless.IsRootless() { - options.Isolation = buildah.IsolationOCIRootless - } - - return r.Runtime.Build(ctx, options, dockerfiles...) -} - -// PruneVolumes is a wrapper function for libpod PruneVolumes -func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) { - return r.Runtime.PruneVolumes(ctx) -} - -// SaveImage is a wrapper function for saving an image to the local filesystem -func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) error { - source := c.InputArgs[0] - additionalTags := c.InputArgs[1:] - - newImage, err := r.Runtime.ImageRuntime().NewFromLocal(source) - if err != nil { - return err - } - return newImage.Save(ctx, source, c.Format, c.Output, additionalTags, c.Quiet, c.Compress) -} - -// LoadImage is a wrapper function for libpod PruneVolumes -func (r *LocalRuntime) LoadImage(ctx context.Context, name string, cli *cliconfig.LoadValues) (string, error) { - var ( - writer io.Writer - ) - if !cli.Quiet { - writer = os.Stderr - } - return r.Runtime.LoadImage(ctx, name, cli.Input, writer, cli.SignaturePolicy) -} diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go deleted file mode 100644 index ca2fad852..000000000 --- a/libpod/adapter/runtime_remote.go +++ /dev/null @@ -1,798 +0,0 @@ -// +build remoteclient - -package adapter - -import ( - "bufio" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "strings" - "time" - - "github.com/containers/buildah/imagebuildah" - "github.com/containers/image/docker/reference" - "github.com/containers/image/types" - "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/varlink" - "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/image" - "github.com/containers/libpod/utils" - "github.com/containers/storage/pkg/archive" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/varlink/go/varlink" -) - -// ImageRuntime is wrapper for image runtime -type RemoteImageRuntime struct{} - -// RemoteRuntime describes a wrapper runtime struct -type RemoteRuntime struct { - Conn *varlink.Connection - Remote bool -} - -// LocalRuntime describes a typical libpod runtime -type LocalRuntime struct { - *RemoteRuntime -} - -// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it -func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) { - runtime := RemoteRuntime{} - conn, err := runtime.Connect() - if err != nil { - return nil, err - } - rr := RemoteRuntime{ - Conn: conn, - Remote: true, - } - foo := LocalRuntime{ - &rr, - } - return &foo, nil -} - -// Shutdown is a bogus wrapper for compat with the libpod runtime -func (r RemoteRuntime) Shutdown(force bool) error { - return nil -} - -// ContainerImage -type ContainerImage struct { - remoteImage -} - -type remoteImage struct { - ID string - Labels map[string]string - RepoTags []string - RepoDigests []string - Parent string - Size int64 - Created time.Time - InputName string - Names []string - Digest digest.Digest - isParent bool - Runtime *LocalRuntime -} - -// Container ... -type Container struct { - remoteContainer -} - -// remoteContainer .... -type remoteContainer struct { - Runtime *LocalRuntime - config *libpod.ContainerConfig - state *libpod.ContainerState -} - -type VolumeFilter func(*Volume) bool - -// Volume is embed for libpod volumes -type Volume struct { - remoteVolume -} - -type remoteVolume struct { - Runtime *LocalRuntime - config *libpod.VolumeConfig -} - -// GetImages returns a slice of containerimages over a varlink connection -func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { - var newImages []*ContainerImage - images, err := iopodman.ListImages().Call(r.Conn) - if err != nil { - return nil, err - } - for _, i := range images { - name := i.Id - if len(i.RepoTags) > 1 { - name = i.RepoTags[0] - } - newImage, err := imageInListToContainerImage(i, name, r) - if err != nil { - return nil, err - } - newImages = append(newImages, newImage) - } - return newImages, nil -} - -func imageInListToContainerImage(i iopodman.Image, name string, runtime *LocalRuntime) (*ContainerImage, error) { - created, err := time.ParseInLocation(time.RFC3339, i.Created, time.UTC) - if err != nil { - return nil, err - } - ri := remoteImage{ - InputName: name, - ID: i.Id, - Labels: i.Labels, - RepoTags: i.RepoTags, - RepoDigests: i.RepoTags, - Parent: i.ParentId, - Size: i.Size, - Created: created, - Names: i.RepoTags, - isParent: i.IsParent, - Runtime: runtime, - } - return &ContainerImage{ri}, nil -} - -// NewImageFromLocal returns a container image representation of a image over varlink -func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { - img, err := iopodman.GetImage().Call(r.Conn, name) - if err != nil { - return nil, err - } - return imageInListToContainerImage(img, name, r) - -} - -// LoadFromArchiveReference creates an image from a local archive -func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) { - var iid string - // TODO We need to find a way to leak certDir, creds, and the tlsverify into this function, normally this would - // come from cli options but we don't want want those in here either. - tlsverify := true - reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, srcRef.DockerReference().String(), "", "", signaturePolicyPath, &tlsverify) - if err != nil { - return nil, err - } - - for { - responses, flags, err := reply() - if err != nil { - return nil, err - } - for _, line := range responses.Logs { - fmt.Print(line) - } - iid = responses.Id - if flags&varlink.Continues == 0 { - break - } - } - - newImage, err := r.NewImageFromLocal(iid) - if err != nil { - return nil, err - } - return []*ContainerImage{newImage}, nil -} - -// New calls into local storage to look for an image in local storage or to pull it -func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool, label *string) (*ContainerImage, error) { - var iid string - if label != nil { - return nil, errors.New("the remote client function does not support checking a remote image for a label") - } - var ( - tlsVerify bool - tlsVerifyPtr *bool - ) - if dockeroptions.DockerInsecureSkipTLSVerify == types.OptionalBoolFalse { - tlsVerify = true - tlsVerifyPtr = &tlsVerify - - } - if dockeroptions.DockerInsecureSkipTLSVerify == types.OptionalBoolTrue { - tlsVerify = false - tlsVerifyPtr = &tlsVerify - } - - reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, name, dockeroptions.DockerCertPath, "", signaturePolicyPath, tlsVerifyPtr) - if err != nil { - return nil, err - } - for { - responses, flags, err := reply() - if err != nil { - return nil, err - } - for _, line := range responses.Logs { - fmt.Print(line) - } - iid = responses.Id - if flags&varlink.Continues == 0 { - break - } - } - newImage, err := r.NewImageFromLocal(iid) - if err != nil { - return nil, err - } - return newImage, nil -} - -// IsParent goes through the layers in the store and checks if i.TopLayer is -// the parent of any other layer in store. Double check that image with that -// layer exists as well. -func (ci *ContainerImage) IsParent() (bool, error) { - return ci.remoteImage.isParent, nil -} - -// ID returns the image ID as a string -func (ci *ContainerImage) ID() string { - return ci.remoteImage.ID -} - -// Names returns a string array of names associated with the image -func (ci *ContainerImage) Names() []string { - return ci.remoteImage.Names -} - -// Created returns the time the image was created -func (ci *ContainerImage) Created() time.Time { - return ci.remoteImage.Created -} - -// Size returns the size of the image -func (ci *ContainerImage) Size(ctx context.Context) (*uint64, error) { - usize := uint64(ci.remoteImage.Size) - return &usize, nil -} - -// Digest returns the image's digest -func (ci *ContainerImage) Digest() digest.Digest { - return ci.remoteImage.Digest -} - -// Labels returns a map of the image's labels -func (ci *ContainerImage) Labels(ctx context.Context) (map[string]string, error) { - return ci.remoteImage.Labels, nil -} - -// Dangling returns a bool if the image is "dangling" -func (ci *ContainerImage) Dangling() bool { - return len(ci.Names()) == 0 -} - -// TagImage ... -func (ci *ContainerImage) TagImage(tag string) error { - _, err := iopodman.TagImage().Call(ci.Runtime.Conn, ci.ID(), tag) - return err -} - -// RemoveImage calls varlink to remove an image -func (r *LocalRuntime) RemoveImage(ctx context.Context, img *ContainerImage, force bool) (string, error) { - return iopodman.RemoveImage().Call(r.Conn, img.InputName, force) -} - -// History returns the history of an image and its layers -func (ci *ContainerImage) History(ctx context.Context) ([]*image.History, error) { - var imageHistories []*image.History - - reply, err := iopodman.HistoryImage().Call(ci.Runtime.Conn, ci.InputName) - if err != nil { - return nil, err - } - for _, h := range reply { - created, err := time.ParseInLocation(time.RFC3339, h.Created, time.UTC) - if err != nil { - return nil, err - } - ih := image.History{ - ID: h.Id, - Created: &created, - CreatedBy: h.CreatedBy, - Size: h.Size, - Comment: h.Comment, - } - imageHistories = append(imageHistories, &ih) - } - return imageHistories, nil -} - -// LookupContainer gets basic information about container over a varlink -// connection and then translates it to a *Container -func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { - state, err := r.ContainerState(idOrName) - if err != nil { - return nil, err - } - config := r.Config(idOrName) - if err != nil { - return nil, err - } - - rc := remoteContainer{ - r, - config, - state, - } - - c := Container{ - rc, - } - return &c, nil -} - -func (r *LocalRuntime) GetLatestContainer() (*Container, error) { - return nil, libpod.ErrNotImplemented -} - -// ContainerState returns the "state" of the container. -func (r *LocalRuntime) ContainerState(name string) (*libpod.ContainerState, error) { //no-lint - reply, err := iopodman.ContainerStateData().Call(r.Conn, name) - if err != nil { - return nil, err - } - data := libpod.ContainerState{} - if err := json.Unmarshal([]byte(reply), &data); err != nil { - return nil, err - } - return &data, err - -} - -// Config returns a container config -func (r *LocalRuntime) Config(name string) *libpod.ContainerConfig { - // TODO the Spec being returned is not populated. Matt and I could not figure out why. Will defer - // further looking into it for after devconf. - // The libpod function for this has no errors so we are kind of in a tough - // spot here. Logging the errors for now. - reply, err := iopodman.ContainerConfig().Call(r.Conn, name) - if err != nil { - logrus.Error("call to container.config failed") - } - data := libpod.ContainerConfig{} - if err := json.Unmarshal([]byte(reply), &data); err != nil { - logrus.Error("failed to unmarshal container inspect data") - } - return &data - -} - -// PruneImages is the wrapper call for a remote-client to prune images -func (r *LocalRuntime) PruneImages(all bool) ([]string, error) { - return iopodman.ImagesPrune().Call(r.Conn, all) -} - -// Export is a wrapper to container export to a tarfile -func (r *LocalRuntime) Export(name string, path string) error { - tempPath, err := iopodman.ExportContainer().Call(r.Conn, name, "") - if err != nil { - return err - } - return r.GetFileFromRemoteHost(tempPath, path, true) -} - -func (r *LocalRuntime) GetFileFromRemoteHost(remoteFilePath, outputPath string, delete bool) error { - outputFile, err := os.Create(outputPath) - if err != nil { - return err - } - defer outputFile.Close() - - writer := bufio.NewWriter(outputFile) - defer writer.Flush() - - reply, err := iopodman.ReceiveFile().Send(r.Conn, varlink.Upgrade, remoteFilePath, delete) - if err != nil { - return err - } - - length, _, err := reply() - if err != nil { - return errors.Wrap(err, "unable to get file length for transfer") - } - - reader := r.Conn.Reader - if _, err := io.CopyN(writer, reader, length); err != nil { - return errors.Wrap(err, "file transer failed") - } - return nil -} - -// Import implements the remote calls required to import a container image to the store -func (r *LocalRuntime) Import(ctx context.Context, source, reference string, changes []string, history string, quiet bool) (string, error) { - // First we send the file to the host - tempFile, err := r.SendFileOverVarlink(source) - if err != nil { - return "", err - } - return iopodman.ImportImage().Call(r.Conn, strings.TrimRight(tempFile, ":"), reference, history, changes, true) -} - -func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) error { - buildOptions := iopodman.BuildOptions{ - AddHosts: options.CommonBuildOpts.AddHost, - CgroupParent: options.CommonBuildOpts.CgroupParent, - CpuPeriod: int64(options.CommonBuildOpts.CPUPeriod), - CpuQuota: options.CommonBuildOpts.CPUQuota, - CpuShares: int64(options.CommonBuildOpts.CPUShares), - CpusetCpus: options.CommonBuildOpts.CPUSetMems, - CpusetMems: options.CommonBuildOpts.CPUSetMems, - Memory: options.CommonBuildOpts.Memory, - MemorySwap: options.CommonBuildOpts.MemorySwap, - ShmSize: options.CommonBuildOpts.ShmSize, - Ulimit: options.CommonBuildOpts.Ulimit, - Volume: options.CommonBuildOpts.Volumes, - } - - buildinfo := iopodman.BuildInfo{ - AdditionalTags: options.AdditionalTags, - Annotations: options.Annotations, - BuildArgs: options.Args, - BuildOptions: buildOptions, - CniConfigDir: options.CNIConfigDir, - CniPluginDir: options.CNIPluginPath, - Compression: string(options.Compression), - DefaultsMountFilePath: options.DefaultMountsFilePath, - Dockerfiles: dockerfiles, - //Err: string(options.Err), - ForceRmIntermediateCtrs: options.ForceRmIntermediateCtrs, - Iidfile: options.IIDFile, - Label: options.Labels, - Layers: options.Layers, - Nocache: options.NoCache, - //Out: - Output: options.Output, - OutputFormat: options.OutputFormat, - PullPolicy: options.PullPolicy.String(), - Quiet: options.Quiet, - RemoteIntermediateCtrs: options.RemoveIntermediateCtrs, - //ReportWriter: - RuntimeArgs: options.RuntimeArgs, - SignaturePolicyPath: options.SignaturePolicyPath, - Squash: options.Squash, - } - // tar the file - outputFile, err := ioutil.TempFile("", "varlink_tar_send") - if err != nil { - return err - } - defer outputFile.Close() - defer os.Remove(outputFile.Name()) - - // Create the tarball of the context dir to a tempfile - if err := utils.TarToFilesystem(options.ContextDirectory, outputFile); err != nil { - return err - } - // Send the context dir tarball over varlink. - tempFile, err := r.SendFileOverVarlink(outputFile.Name()) - if err != nil { - return err - } - buildinfo.ContextDir = tempFile - - reply, err := iopodman.BuildImage().Send(r.Conn, varlink.More, buildinfo) - if err != nil { - return err - } - - for { - responses, flags, err := reply() - if err != nil { - return err - } - for _, line := range responses.Logs { - fmt.Print(line) - } - if flags&varlink.Continues == 0 { - break - } - } - return err -} - -// SendFileOverVarlink sends a file over varlink in an upgraded connection -func (r *LocalRuntime) SendFileOverVarlink(source string) (string, error) { - fs, err := os.Open(source) - if err != nil { - return "", err - } - - fileInfo, err := fs.Stat() - if err != nil { - return "", err - } - logrus.Debugf("sending %s over varlink connection", source) - reply, err := iopodman.SendFile().Send(r.Conn, varlink.Upgrade, "", int64(fileInfo.Size())) - if err != nil { - return "", err - } - _, _, err = reply() - if err != nil { - return "", err - } - - reader := bufio.NewReader(fs) - _, err = reader.WriteTo(r.Conn.Writer) - if err != nil { - return "", err - } - logrus.Debugf("file transfer complete for %s", source) - r.Conn.Writer.Flush() - - // All was sent, wait for the ACK from the server - tempFile, err := r.Conn.Reader.ReadString(':') - if err != nil { - return "", err - } - - // r.Conn is kaput at this point due to the upgrade - if err := r.RemoteRuntime.RefreshConnection(); err != nil { - return "", err - - } - - return strings.Replace(tempFile, ":", "", -1), nil -} - -// GetAllVolumes retrieves all the volumes -func (r *LocalRuntime) GetAllVolumes() ([]*libpod.Volume, error) { - return nil, libpod.ErrNotImplemented -} - -// RemoveVolume removes a volumes -func (r *LocalRuntime) RemoveVolume(ctx context.Context, v *libpod.Volume, force, prune bool) error { - return libpod.ErrNotImplemented -} - -// GetContainers retrieves all containers from the state -// Filters can be provided which will determine what containers are included in -// the output. Multiple filters are handled by ANDing their output, so only -// containers matching all filters are returned -func (r *LocalRuntime) GetContainers(filters ...libpod.ContainerFilter) ([]*libpod.Container, error) { - return nil, libpod.ErrNotImplemented -} - -// RemoveContainer removes the given container -// If force is specified, the container will be stopped first -// Otherwise, RemoveContainer will return an error if the container is running -func (r *LocalRuntime) RemoveContainer(ctx context.Context, c *libpod.Container, force, volumes bool) error { - return libpod.ErrNotImplemented -} - -// CreateVolume creates a volume over a varlink connection for the remote client -func (r *LocalRuntime) CreateVolume(ctx context.Context, c *cliconfig.VolumeCreateValues, labels, opts map[string]string) (string, error) { - cvOpts := iopodman.VolumeCreateOpts{ - Options: opts, - Labels: labels, - } - if len(c.InputArgs) > 0 { - cvOpts.VolumeName = c.InputArgs[0] - } - - if c.Flag("driver").Changed { - cvOpts.Driver = c.Driver - } - - return iopodman.VolumeCreate().Call(r.Conn, cvOpts) -} - -// RemoveVolumes removes volumes over a varlink connection for the remote client -func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmValues) ([]string, error) { - rmOpts := iopodman.VolumeRemoveOpts{ - All: c.All, - Force: c.Force, - Volumes: c.InputArgs, - } - return iopodman.VolumeRemove().Call(r.Conn, rmOpts) -} - -func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { - - var ( - tls *bool - tlsVerify bool - ) - if dockerRegistryOptions.DockerInsecureSkipTLSVerify == types.OptionalBoolTrue { - tlsVerify = false - tls = &tlsVerify - } - if dockerRegistryOptions.DockerInsecureSkipTLSVerify == types.OptionalBoolFalse { - tlsVerify = true - tls = &tlsVerify - } - - reply, err := iopodman.PushImage().Send(r.Conn, varlink.More, srcName, destination, tls, signaturePolicyPath, "", dockerRegistryOptions.DockerCertPath, forceCompress, manifestMIMEType, signingOptions.RemoveSignatures, signingOptions.SignBy) - if err != nil { - return err - } - for { - responses, flags, err := reply() - if err != nil { - return err - } - for _, line := range responses.Logs { - fmt.Print(line) - } - if flags&varlink.Continues == 0 { - break - } - } - - return err -} - -// InspectVolumes returns a slice of volumes based on an arg list or --all -func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*Volume, error) { - reply, err := iopodman.GetVolumes().Call(r.Conn, c.InputArgs, c.All) - if err != nil { - return nil, err - } - return varlinkVolumeToVolume(r, reply), nil -} - -//Volumes returns a slice of adapter.volumes based on information about libpod -// volumes over a varlink connection -func (r *LocalRuntime) Volumes(ctx context.Context) ([]*Volume, error) { - reply, err := iopodman.GetVolumes().Call(r.Conn, []string{}, true) - if err != nil { - return nil, err - } - return varlinkVolumeToVolume(r, reply), nil -} - -func varlinkVolumeToVolume(r *LocalRuntime, volumes []iopodman.Volume) []*Volume { - var vols []*Volume - for _, v := range volumes { - volumeConfig := libpod.VolumeConfig{ - Name: v.Name, - Labels: v.Labels, - MountPoint: v.MountPoint, - Driver: v.Driver, - Options: v.Options, - Scope: v.Scope, - } - n := remoteVolume{ - Runtime: r, - config: &volumeConfig, - } - newVol := Volume{ - n, - } - vols = append(vols, &newVol) - } - return vols -} - -// PruneVolumes removes all unused volumes from the remote system -func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) { - var errs []error - prunedNames, prunedErrors, err := iopodman.VolumesPrune().Call(r.Conn) - if err != nil { - return []string{}, []error{err} - } - // We need to transform the string results of the error into actual error types - for _, e := range prunedErrors { - errs = append(errs, errors.New(e)) - } - return prunedNames, errs -} - -// SaveImage is a wrapper function for saving an image to the local filesystem -func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) error { - source := c.InputArgs[0] - additionalTags := c.InputArgs[1:] - - options := iopodman.ImageSaveOptions{ - Name: source, - Format: c.Format, - Output: c.Output, - MoreTags: additionalTags, - Quiet: c.Quiet, - Compress: c.Compress, - } - reply, err := iopodman.ImageSave().Send(r.Conn, varlink.More, options) - if err != nil { - return err - } - - var fetchfile string - for { - responses, flags, err := reply() - if err != nil { - return err - } - if len(responses.Id) > 0 { - fetchfile = responses.Id - } - for _, line := range responses.Logs { - fmt.Print(line) - } - if flags&varlink.Continues == 0 { - break - } - - } - if err != nil { - return err - } - - outputToDir := false - outfile := c.Output - var outputFile *os.File - // If the result is supposed to be a dir, then we need to put the tarfile - // from the host in a temporary file - if options.Format != "oci-archive" && options.Format != "docker-archive" { - outputToDir = true - outputFile, err = ioutil.TempFile("", "saveimage_tempfile") - if err != nil { - return err - } - outfile = outputFile.Name() - defer outputFile.Close() - defer os.Remove(outputFile.Name()) - } - // We now need to fetch the tarball result back to the more system - if err := r.GetFileFromRemoteHost(fetchfile, outfile, true); err != nil { - return err - } - - // If the result is a tarball, we're done - // If it is a dir, we need to untar the temporary file into the dir - if outputToDir { - if err := utils.UntarToFileSystem(c.Output, outputFile, &archive.TarOptions{}); err != nil { - return err - } - } - return nil -} - -// LoadImage loads a container image from a remote client's filesystem -func (r *LocalRuntime) LoadImage(ctx context.Context, name string, cli *cliconfig.LoadValues) (string, error) { - var names string - remoteTempFile, err := r.SendFileOverVarlink(cli.Input) - if err != nil { - return "", nil - } - more := varlink.More - if cli.Quiet { - more = 0 - } - reply, err := iopodman.LoadImage().Send(r.Conn, uint64(more), name, remoteTempFile, cli.Quiet, true) - if err != nil { - return "", err - } - - for { - responses, flags, err := reply() - if err != nil { - logrus.Error(err) - return "", err - } - for _, line := range responses.Logs { - fmt.Print(line) - } - names = responses.Id - if flags&varlink.Continues == 0 { - break - } - } - return names, nil -} diff --git a/libpod/adapter/shortcuts/shortcuts.go b/libpod/adapter/shortcuts/shortcuts.go deleted file mode 100644 index 0633399ae..000000000 --- a/libpod/adapter/shortcuts/shortcuts.go +++ /dev/null @@ -1,27 +0,0 @@ -package shortcuts - -import "github.com/containers/libpod/libpod" - -// GetPodsByContext gets pods whether all, latest, or a slice of names/ids -func GetPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) ([]*libpod.Pod, error) { - var outpods []*libpod.Pod - if all { - return runtime.GetAllPods() - } - if latest { - p, err := runtime.GetLatestPod() - if err != nil { - return nil, err - } - outpods = append(outpods, p) - return outpods, nil - } - for _, p := range pods { - pod, err := runtime.LookupPod(p) - if err != nil { - return nil, err - } - outpods = append(outpods, pod) - } - return outpods, nil -} diff --git a/libpod/adapter/volumes_remote.go b/libpod/adapter/volumes_remote.go deleted file mode 100644 index beacd943a..000000000 --- a/libpod/adapter/volumes_remote.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build remoteclient - -package adapter - -// Name returns the name of the volume -func (v *Volume) Name() string { - return v.config.Name -} - -//Labels returns the labels for a volume -func (v *Volume) Labels() map[string]string { - return v.config.Labels -} - -// Driver returns the driver for the volume -func (v *Volume) Driver() string { - return v.config.Driver -} - -// Options returns the options a volume was created with -func (v *Volume) Options() map[string]string { - return v.config.Options -} - -// MountPath returns the path the volume is mounted to -func (v *Volume) MountPoint() string { - return v.config.MountPoint -} - -// Scope returns the scope for an adapter.volume -func (v *Volume) Scope() string { - return v.config.Scope -} diff --git a/pkg/adapter/client.go b/pkg/adapter/client.go new file mode 100644 index 000000000..6512a5952 --- /dev/null +++ b/pkg/adapter/client.go @@ -0,0 +1,47 @@ +// +build remoteclient + +package adapter + +import ( + "os" + + "github.com/sirupsen/logrus" + "github.com/varlink/go/varlink" +) + +// DefaultAddress is the default address of the varlink socket +const DefaultAddress = "unix:/run/podman/io.podman" + +// Connect provides a varlink connection +func (r RemoteRuntime) Connect() (*varlink.Connection, error) { + var err error + var connection *varlink.Connection + if bridge := os.Getenv("PODMAN_VARLINK_BRIDGE"); bridge != "" { + logrus.Infof("Connecting with varlink bridge") + logrus.Debugf("%s", bridge) + connection, err = varlink.NewBridge(bridge) + } else { + address := os.Getenv("PODMAN_VARLINK_ADDRESS") + if address == "" { + address = DefaultAddress + } + logrus.Infof("Connecting with varlink address") + logrus.Debugf("%s", address) + connection, err = varlink.NewConnection(address) + } + if err != nil { + return nil, err + } + return connection, nil +} + +// RefreshConnection is used to replace the current r.Conn after things like +// using an upgraded varlink connection +func (r RemoteRuntime) RefreshConnection() error { + newConn, err := r.Connect() + if err != nil { + return err + } + r.Conn = newConn + return nil +} diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go new file mode 100644 index 000000000..9623304e5 --- /dev/null +++ b/pkg/adapter/containers_remote.go @@ -0,0 +1,50 @@ +// +build remoteclient + +package adapter + +import ( + "encoding/json" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/inspect" +) + +// Inspect returns an inspect struct from varlink +func (c *Container) Inspect(size bool) (*inspect.ContainerInspectData, error) { + reply, err := iopodman.ContainerInspectData().Call(c.Runtime.Conn, c.ID()) + if err != nil { + return nil, err + } + data := inspect.ContainerInspectData{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, err +} + +// ID returns the ID of the container +func (c *Container) ID() string { + return c.config.ID +} + +// GetArtifact returns a container's artifacts +func (c *Container) GetArtifact(name string) ([]byte, error) { + var data []byte + reply, err := iopodman.ContainerArtifacts().Call(c.Runtime.Conn, c.ID(), name) + if err != nil { + return nil, err + } + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return data, err +} + +// Config returns a container's Config ... same as ctr.Config() +func (c *Container) Config() *libpod.ContainerConfig { + if c.config != nil { + return c.config + } + return c.Runtime.Config(c.ID()) +} diff --git a/pkg/adapter/images_remote.go b/pkg/adapter/images_remote.go new file mode 100644 index 000000000..e7b38dccc --- /dev/null +++ b/pkg/adapter/images_remote.go @@ -0,0 +1,24 @@ +// +build remoteclient + +package adapter + +import ( + "context" + "encoding/json" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/pkg/inspect" +) + +// Inspect returns returns an ImageData struct from over a varlink connection +func (i *ContainerImage) Inspect(ctx context.Context) (*inspect.ImageData, error) { + reply, err := iopodman.InspectImage().Call(i.Runtime.Conn, i.ID()) + if err != nil { + return nil, err + } + data := inspect.ImageData{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, nil +} diff --git a/pkg/adapter/info_remote.go b/pkg/adapter/info_remote.go new file mode 100644 index 000000000..3b691ed17 --- /dev/null +++ b/pkg/adapter/info_remote.go @@ -0,0 +1,56 @@ +// +build remoteclient + +package adapter + +import ( + "encoding/json" + + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" +) + +// Info returns information for the host system and its components +func (r RemoteRuntime) Info() ([]libpod.InfoData, error) { + // TODO the varlink implementation for info should be updated to match the output for regular info + var ( + reply []libpod.InfoData + hostInfo map[string]interface{} + store map[string]interface{} + ) + + registries := make(map[string]interface{}) + insecureRegistries := make(map[string]interface{}) + conn, err := r.Connect() + if err != nil { + return nil, err + } + defer conn.Close() + info, err := iopodman.GetInfo().Call(conn) + if err != nil { + return nil, err + } + + // info.host -> map[string]interface{} + h, err := json.Marshal(info.Host) + if err != nil { + return nil, err + } + json.Unmarshal(h, &hostInfo) + + // info.store -> map[string]interface{} + s, err := json.Marshal(info.Store) + if err != nil { + return nil, err + } + json.Unmarshal(s, &store) + + registries["registries"] = info.Registries + insecureRegistries["registries"] = info.Insecure_registries + + // Add everything to the reply + reply = append(reply, libpod.InfoData{Type: "host", Data: hostInfo}) + reply = append(reply, libpod.InfoData{Type: "registries", Data: registries}) + reply = append(reply, libpod.InfoData{Type: "insecure registries", Data: insecureRegistries}) + reply = append(reply, libpod.InfoData{Type: "store", Data: store}) + return reply, nil +} diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go new file mode 100644 index 000000000..f2bcbd473 --- /dev/null +++ b/pkg/adapter/pods.go @@ -0,0 +1,152 @@ +// +build !remoteclient + +package adapter + +import ( + "context" + "github.com/containers/libpod/pkg/adapter/shortcuts" + + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/libpod" +) + +// Pod ... +type Pod struct { + *libpod.Pod +} + +// RemovePods ... +func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) { + var ( + errs []error + podids []string + ) + pods, err := shortcuts.GetPodsByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + if err != nil { + errs = append(errs, err) + return nil, errs + } + + for _, p := range pods { + if err := r.RemovePod(ctx, p, cli.Force, cli.Force); err != nil { + errs = append(errs, err) + } else { + podids = append(podids, p.ID()) + } + } + return podids, errs +} + +// GetLatestPod gets the latest pod and wraps it in an adapter pod +func (r *LocalRuntime) GetLatestPod() (*Pod, error) { + pod := Pod{} + p, err := r.Runtime.GetLatestPod() + pod.Pod = p + return &pod, err +} + +// LookupPod gets a pod by name or id and wraps it in an adapter pod +func (r *LocalRuntime) LookupPod(nameOrID string) (*Pod, error) { + pod := Pod{} + p, err := r.Runtime.LookupPod(nameOrID) + pod.Pod = p + return &pod, err +} + +// StopPods is a wrapper to libpod to stop pods based on a cli context +func (r *LocalRuntime) StopPods(ctx context.Context, cli *cliconfig.PodStopValues) ([]string, []error) { + timeout := -1 + if cli.Flags().Changed("timeout") { + timeout = int(cli.Timeout) + } + var ( + errs []error + podids []string + ) + pods, err := shortcuts.GetPodsByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + if err != nil { + errs = append(errs, err) + return nil, errs + } + + for _, p := range pods { + stopped := true + conErrs, stopErr := p.StopWithTimeout(ctx, true, int(timeout)) + if stopErr != nil { + errs = append(errs, stopErr) + stopped = false + } + if conErrs != nil { + stopped = false + for _, err := range conErrs { + errs = append(errs, err) + } + } + if stopped { + podids = append(podids, p.ID()) + } + } + return podids, errs +} + +// KillPods is a wrapper to libpod to start pods based on the cli context +func (r *LocalRuntime) KillPods(ctx context.Context, cli *cliconfig.PodKillValues, signal uint) ([]string, []error) { + var ( + errs []error + podids []string + ) + pods, err := shortcuts.GetPodsByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + if err != nil { + errs = append(errs, err) + return nil, errs + } + for _, p := range pods { + killed := true + conErrs, killErr := p.Kill(signal) + if killErr != nil { + errs = append(errs, killErr) + killed = false + } + if conErrs != nil { + killed = false + for _, err := range conErrs { + errs = append(errs, err) + } + } + if killed { + podids = append(podids, p.ID()) + } + } + return podids, errs +} + +// StartPods is a wrapper to start pods based on the cli context +func (r *LocalRuntime) StartPods(ctx context.Context, cli *cliconfig.PodStartValues) ([]string, []error) { + var ( + errs []error + podids []string + ) + pods, err := shortcuts.GetPodsByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + if err != nil { + errs = append(errs, err) + return nil, errs + } + for _, p := range pods { + started := true + conErrs, startErr := p.Start(ctx) + if startErr != nil { + errs = append(errs, startErr) + started = false + } + if conErrs != nil { + started = false + for _, err := range conErrs { + errs = append(errs, err) + } + } + if started { + podids = append(podids, p.ID()) + } + } + return podids, errs +} diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go new file mode 100644 index 000000000..04484780a --- /dev/null +++ b/pkg/adapter/pods_remote.go @@ -0,0 +1,170 @@ +// +build remoteclient + +package adapter + +import ( + "context" + "encoding/json" + + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" + "github.com/pkg/errors" + "github.com/ulule/deepcopier" +) + +// Pod ... +type Pod struct { + remotepod +} + +type remotepod struct { + config *libpod.PodConfig + state *libpod.PodInspectState + containers []libpod.PodContainerInfo + Runtime *LocalRuntime +} + +// RemovePods removes one or more based on the cli context. +func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) { + var ( + rmErrs []error + rmPods []string + ) + podIDs, err := iopodman.GetPodsByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs) + if err != nil { + rmErrs = append(rmErrs, err) + return nil, rmErrs + } + + for _, p := range podIDs { + reply, err := iopodman.RemovePod().Call(r.Conn, p, cli.Force) + if err != nil { + rmErrs = append(rmErrs, err) + } else { + rmPods = append(rmPods, reply) + } + } + return rmPods, rmErrs +} + +// Inspect looks up a pod by name or id and embeds its data into a remote pod +// object. +func (r *LocalRuntime) Inspect(nameOrID string) (*Pod, error) { + reply, err := iopodman.PodStateData().Call(r.Conn, nameOrID) + if err != nil { + return nil, err + } + data := libpod.PodInspect{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + pod := Pod{} + pod.Runtime = r + pod.config = data.Config + pod.state = data.State + pod.containers = data.Containers + return &pod, nil +} + +// GetLatestPod gets the latest pod and wraps it in an adapter pod +func (r *LocalRuntime) GetLatestPod() (*Pod, error) { + reply, err := iopodman.GetPodsByContext().Call(r.Conn, false, true, nil) + if err != nil { + return nil, err + } + if len(reply) > 0 { + return r.Inspect(reply[0]) + } + return nil, errors.New("no pods exist") +} + +// LookupPod gets a pod by name or ID and wraps it in an adapter pod +func (r *LocalRuntime) LookupPod(nameOrID string) (*Pod, error) { + return r.Inspect(nameOrID) +} + +// Inspect, like libpod pod inspect, returns a libpod.PodInspect object from +// the data of a remotepod data struct +func (p *Pod) Inspect() (*libpod.PodInspect, error) { + config := new(libpod.PodConfig) + deepcopier.Copy(p.remotepod.config).To(config) + inspectData := libpod.PodInspect{ + Config: config, + State: p.remotepod.state, + Containers: p.containers, + } + return &inspectData, nil +} + +// StopPods stops pods based on the cli context from the remote client. +func (r *LocalRuntime) StopPods(ctx context.Context, cli *cliconfig.PodStopValues) ([]string, []error) { + var ( + stopErrs []error + stopPods []string + ) + var timeout int64 = -1 + if cli.Flags().Changed("timeout") { + timeout = int64(cli.Timeout) + } + podIDs, err := iopodman.GetPodsByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs) + if err != nil { + return nil, []error{err} + } + + for _, p := range podIDs { + podID, err := iopodman.StopPod().Call(r.Conn, p, timeout) + if err != nil { + stopErrs = append(stopErrs, err) + } else { + stopPods = append(stopPods, podID) + } + } + return stopPods, stopErrs +} + +// KillPods kills pods over varlink for the remoteclient +func (r *LocalRuntime) KillPods(ctx context.Context, cli *cliconfig.PodKillValues, signal uint) ([]string, []error) { + var ( + killErrs []error + killPods []string + ) + + podIDs, err := iopodman.GetPodsByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs) + if err != nil { + return nil, []error{err} + } + + for _, p := range podIDs { + podID, err := iopodman.KillPod().Call(r.Conn, p, int64(signal)) + if err != nil { + killErrs = append(killErrs, err) + } else { + killPods = append(killPods, podID) + } + } + return killPods, killErrs +} + +// StartPods starts pods for the remote client over varlink +func (r *LocalRuntime) StartPods(ctx context.Context, cli *cliconfig.PodStartValues) ([]string, []error) { + var ( + startErrs []error + startPods []string + ) + + podIDs, err := iopodman.GetPodsByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs) + if err != nil { + return nil, []error{err} + } + + for _, p := range podIDs { + podID, err := iopodman.StartPod().Call(r.Conn, p) + if err != nil { + startErrs = append(startErrs, err) + } else { + startPods = append(startPods, podID) + } + } + return startPods, startErrs +} diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go new file mode 100644 index 000000000..4f5b98dbb --- /dev/null +++ b/pkg/adapter/runtime.go @@ -0,0 +1,335 @@ +// +build !remoteclient + +package adapter + +import ( + "context" + "io" + "io/ioutil" + "os" + "strconv" + + "github.com/containers/buildah" + "github.com/containers/buildah/imagebuildah" + "github.com/containers/buildah/pkg/parse" + "github.com/containers/image/docker/reference" + "github.com/containers/image/types" + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/rootless" + "github.com/pkg/errors" +) + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + *libpod.Runtime + Remote bool +} + +// ContainerImage ... +type ContainerImage struct { + *image.Image +} + +// Container ... +type Container struct { + *libpod.Container +} + +// Volume ... +type Volume struct { + *libpod.Volume +} + +// VolumeFilter is for filtering volumes on the client +type VolumeFilter func(*Volume) bool + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) { + runtime, err := libpodruntime.GetRuntime(c) + if err != nil { + return nil, err + } + return &LocalRuntime{ + Runtime: runtime, + }, nil +} + +// GetImages returns a slice of images in containerimages +func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { + var containerImages []*ContainerImage + images, err := r.Runtime.ImageRuntime().GetImages() + if err != nil { + return nil, err + } + for _, i := range images { + containerImages = append(containerImages, &ContainerImage{i}) + } + return containerImages, nil + +} + +// NewImageFromLocal returns a containerimage representation of a image from local storage +func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { + img, err := r.Runtime.ImageRuntime().NewFromLocal(name) + if err != nil { + return nil, err + } + return &ContainerImage{img}, nil +} + +// LoadFromArchiveReference calls into local storage to load an image from an archive +func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) { + var containerImages []*ContainerImage + imgs, err := r.Runtime.ImageRuntime().LoadFromArchiveReference(ctx, srcRef, signaturePolicyPath, writer) + if err != nil { + return nil, err + } + for _, i := range imgs { + ci := ContainerImage{i} + containerImages = append(containerImages, &ci) + } + return containerImages, nil +} + +// New calls into local storage to look for an image in local storage or to pull it +func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool, label *string) (*ContainerImage, error) { + img, err := r.Runtime.ImageRuntime().New(ctx, name, signaturePolicyPath, authfile, writer, dockeroptions, signingoptions, forcePull, label) + if err != nil { + return nil, err + } + return &ContainerImage{img}, nil +} + +// RemoveImage calls into local storage and removes an image +func (r *LocalRuntime) RemoveImage(ctx context.Context, img *ContainerImage, force bool) (string, error) { + return r.Runtime.RemoveImage(ctx, img.Image, force) +} + +// LookupContainer ... +func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { + ctr, err := r.Runtime.LookupContainer(idOrName) + if err != nil { + return nil, err + } + return &Container{ctr}, nil +} + +// PruneImages is wrapper into PruneImages within the image pkg +func (r *LocalRuntime) PruneImages(all bool) ([]string, error) { + return r.ImageRuntime().PruneImages(all) +} + +// Export is a wrapper to container export to a tarfile +func (r *LocalRuntime) Export(name string, path string) error { + ctr, err := r.Runtime.LookupContainer(name) + if err != nil { + return errors.Wrapf(err, "error looking up container %q", name) + } + if os.Geteuid() != 0 { + state, err := ctr.State() + if err != nil { + return errors.Wrapf(err, "cannot read container state %q", ctr.ID()) + } + if state == libpod.ContainerStateRunning || state == libpod.ContainerStatePaused { + data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile) + if err != nil { + return errors.Wrapf(err, "cannot read conmon PID file %q", ctr.Config().ConmonPidFile) + } + conmonPid, err := strconv.Atoi(string(data)) + if err != nil { + return errors.Wrapf(err, "cannot parse PID %q", data) + } + became, ret, err := rootless.JoinDirectUserAndMountNS(uint(conmonPid)) + if err != nil { + return err + } + if became { + os.Exit(ret) + } + } else { + became, ret, err := rootless.BecomeRootInUserNS() + if err != nil { + return err + } + if became { + os.Exit(ret) + } + } + } + + return ctr.Export(path) +} + +// Import is a wrapper to import a container image +func (r *LocalRuntime) Import(ctx context.Context, source, reference string, changes []string, history string, quiet bool) (string, error) { + return r.Runtime.Import(ctx, source, reference, changes, history, quiet) +} + +// CreateVolume is a wrapper to create volumes +func (r *LocalRuntime) CreateVolume(ctx context.Context, c *cliconfig.VolumeCreateValues, labels, opts map[string]string) (string, error) { + var ( + options []libpod.VolumeCreateOption + volName string + ) + + if len(c.InputArgs) > 0 { + volName = c.InputArgs[0] + options = append(options, libpod.WithVolumeName(volName)) + } + + if c.Flag("driver").Changed { + options = append(options, libpod.WithVolumeDriver(c.Driver)) + } + + if len(labels) != 0 { + options = append(options, libpod.WithVolumeLabels(labels)) + } + + if len(options) != 0 { + options = append(options, libpod.WithVolumeOptions(opts)) + } + newVolume, err := r.NewVolume(ctx, options...) + if err != nil { + return "", err + } + return newVolume.Name(), nil +} + +// RemoveVolumes is a wrapper to remove volumes +func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmValues) ([]string, error) { + return r.Runtime.RemoveVolumes(ctx, c.InputArgs, c.All, c.Force) +} + +// Push is a wrapper to push an image to a registry +func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { + newImage, err := r.ImageRuntime().NewFromLocal(srcName) + if err != nil { + return err + } + return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil) +} + +// InspectVolumes returns a slice of volumes based on an arg list or --all +func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*Volume, error) { + var ( + volumes []*libpod.Volume + err error + ) + + if c.All { + volumes, err = r.GetAllVolumes() + } else { + for _, v := range c.InputArgs { + vol, err := r.GetVolume(v) + if err != nil { + return nil, err + } + volumes = append(volumes, vol) + } + } + if err != nil { + return nil, err + } + return libpodVolumeToVolume(volumes), nil +} + +// Volumes returns a slice of localruntime volumes +func (r *LocalRuntime) Volumes(ctx context.Context) ([]*Volume, error) { + vols, err := r.GetAllVolumes() + if err != nil { + return nil, err + } + return libpodVolumeToVolume(vols), nil +} + +// libpodVolumeToVolume converts a slice of libpod volumes to a slice +// of localruntime volumes (same as libpod) +func libpodVolumeToVolume(volumes []*libpod.Volume) []*Volume { + var vols []*Volume + for _, v := range volumes { + newVol := Volume{ + v, + } + vols = append(vols, &newVol) + } + return vols +} + +// Build is the wrapper to build images +func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) error { + namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command) + if err != nil { + return errors.Wrapf(err, "error parsing namespace-related options") + } + usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command) + if err != nil { + return errors.Wrapf(err, "error parsing ID mapping options") + } + namespaceOptions.AddOrReplace(usernsOption...) + + systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command) + if err != nil { + return errors.Wrapf(err, "error building system context") + } + + authfile := c.Authfile + if len(c.Authfile) == 0 { + authfile = os.Getenv("REGISTRY_AUTH_FILE") + } + + systemContext.AuthFilePath = authfile + commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command) + if err != nil { + return err + } + + options.NamespaceOptions = namespaceOptions + options.ConfigureNetwork = networkPolicy + options.IDMappingOptions = idmappingOptions + options.CommonBuildOpts = commonOpts + options.SystemContext = systemContext + + if c.Flag("runtime").Changed { + options.Runtime = r.GetOCIRuntimePath() + } + if c.Quiet { + options.ReportWriter = ioutil.Discard + } + + if rootless.IsRootless() { + options.Isolation = buildah.IsolationOCIRootless + } + + return r.Runtime.Build(ctx, options, dockerfiles...) +} + +// PruneVolumes is a wrapper function for libpod PruneVolumes +func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) { + return r.Runtime.PruneVolumes(ctx) +} + +// SaveImage is a wrapper function for saving an image to the local filesystem +func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) error { + source := c.InputArgs[0] + additionalTags := c.InputArgs[1:] + + newImage, err := r.Runtime.ImageRuntime().NewFromLocal(source) + if err != nil { + return err + } + return newImage.Save(ctx, source, c.Format, c.Output, additionalTags, c.Quiet, c.Compress) +} + +// LoadImage is a wrapper function for libpod PruneVolumes +func (r *LocalRuntime) LoadImage(ctx context.Context, name string, cli *cliconfig.LoadValues) (string, error) { + var ( + writer io.Writer + ) + if !cli.Quiet { + writer = os.Stderr + } + return r.Runtime.LoadImage(ctx, name, cli.Input, writer, cli.SignaturePolicy) +} diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go new file mode 100644 index 000000000..ca2fad852 --- /dev/null +++ b/pkg/adapter/runtime_remote.go @@ -0,0 +1,798 @@ +// +build remoteclient + +package adapter + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "strings" + "time" + + "github.com/containers/buildah/imagebuildah" + "github.com/containers/image/docker/reference" + "github.com/containers/image/types" + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/utils" + "github.com/containers/storage/pkg/archive" + "github.com/opencontainers/go-digest" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/varlink/go/varlink" +) + +// ImageRuntime is wrapper for image runtime +type RemoteImageRuntime struct{} + +// RemoteRuntime describes a wrapper runtime struct +type RemoteRuntime struct { + Conn *varlink.Connection + Remote bool +} + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + *RemoteRuntime +} + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) { + runtime := RemoteRuntime{} + conn, err := runtime.Connect() + if err != nil { + return nil, err + } + rr := RemoteRuntime{ + Conn: conn, + Remote: true, + } + foo := LocalRuntime{ + &rr, + } + return &foo, nil +} + +// Shutdown is a bogus wrapper for compat with the libpod runtime +func (r RemoteRuntime) Shutdown(force bool) error { + return nil +} + +// ContainerImage +type ContainerImage struct { + remoteImage +} + +type remoteImage struct { + ID string + Labels map[string]string + RepoTags []string + RepoDigests []string + Parent string + Size int64 + Created time.Time + InputName string + Names []string + Digest digest.Digest + isParent bool + Runtime *LocalRuntime +} + +// Container ... +type Container struct { + remoteContainer +} + +// remoteContainer .... +type remoteContainer struct { + Runtime *LocalRuntime + config *libpod.ContainerConfig + state *libpod.ContainerState +} + +type VolumeFilter func(*Volume) bool + +// Volume is embed for libpod volumes +type Volume struct { + remoteVolume +} + +type remoteVolume struct { + Runtime *LocalRuntime + config *libpod.VolumeConfig +} + +// GetImages returns a slice of containerimages over a varlink connection +func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { + var newImages []*ContainerImage + images, err := iopodman.ListImages().Call(r.Conn) + if err != nil { + return nil, err + } + for _, i := range images { + name := i.Id + if len(i.RepoTags) > 1 { + name = i.RepoTags[0] + } + newImage, err := imageInListToContainerImage(i, name, r) + if err != nil { + return nil, err + } + newImages = append(newImages, newImage) + } + return newImages, nil +} + +func imageInListToContainerImage(i iopodman.Image, name string, runtime *LocalRuntime) (*ContainerImage, error) { + created, err := time.ParseInLocation(time.RFC3339, i.Created, time.UTC) + if err != nil { + return nil, err + } + ri := remoteImage{ + InputName: name, + ID: i.Id, + Labels: i.Labels, + RepoTags: i.RepoTags, + RepoDigests: i.RepoTags, + Parent: i.ParentId, + Size: i.Size, + Created: created, + Names: i.RepoTags, + isParent: i.IsParent, + Runtime: runtime, + } + return &ContainerImage{ri}, nil +} + +// NewImageFromLocal returns a container image representation of a image over varlink +func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { + img, err := iopodman.GetImage().Call(r.Conn, name) + if err != nil { + return nil, err + } + return imageInListToContainerImage(img, name, r) + +} + +// LoadFromArchiveReference creates an image from a local archive +func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) { + var iid string + // TODO We need to find a way to leak certDir, creds, and the tlsverify into this function, normally this would + // come from cli options but we don't want want those in here either. + tlsverify := true + reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, srcRef.DockerReference().String(), "", "", signaturePolicyPath, &tlsverify) + if err != nil { + return nil, err + } + + for { + responses, flags, err := reply() + if err != nil { + return nil, err + } + for _, line := range responses.Logs { + fmt.Print(line) + } + iid = responses.Id + if flags&varlink.Continues == 0 { + break + } + } + + newImage, err := r.NewImageFromLocal(iid) + if err != nil { + return nil, err + } + return []*ContainerImage{newImage}, nil +} + +// New calls into local storage to look for an image in local storage or to pull it +func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool, label *string) (*ContainerImage, error) { + var iid string + if label != nil { + return nil, errors.New("the remote client function does not support checking a remote image for a label") + } + var ( + tlsVerify bool + tlsVerifyPtr *bool + ) + if dockeroptions.DockerInsecureSkipTLSVerify == types.OptionalBoolFalse { + tlsVerify = true + tlsVerifyPtr = &tlsVerify + + } + if dockeroptions.DockerInsecureSkipTLSVerify == types.OptionalBoolTrue { + tlsVerify = false + tlsVerifyPtr = &tlsVerify + } + + reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, name, dockeroptions.DockerCertPath, "", signaturePolicyPath, tlsVerifyPtr) + if err != nil { + return nil, err + } + for { + responses, flags, err := reply() + if err != nil { + return nil, err + } + for _, line := range responses.Logs { + fmt.Print(line) + } + iid = responses.Id + if flags&varlink.Continues == 0 { + break + } + } + newImage, err := r.NewImageFromLocal(iid) + if err != nil { + return nil, err + } + return newImage, nil +} + +// IsParent goes through the layers in the store and checks if i.TopLayer is +// the parent of any other layer in store. Double check that image with that +// layer exists as well. +func (ci *ContainerImage) IsParent() (bool, error) { + return ci.remoteImage.isParent, nil +} + +// ID returns the image ID as a string +func (ci *ContainerImage) ID() string { + return ci.remoteImage.ID +} + +// Names returns a string array of names associated with the image +func (ci *ContainerImage) Names() []string { + return ci.remoteImage.Names +} + +// Created returns the time the image was created +func (ci *ContainerImage) Created() time.Time { + return ci.remoteImage.Created +} + +// Size returns the size of the image +func (ci *ContainerImage) Size(ctx context.Context) (*uint64, error) { + usize := uint64(ci.remoteImage.Size) + return &usize, nil +} + +// Digest returns the image's digest +func (ci *ContainerImage) Digest() digest.Digest { + return ci.remoteImage.Digest +} + +// Labels returns a map of the image's labels +func (ci *ContainerImage) Labels(ctx context.Context) (map[string]string, error) { + return ci.remoteImage.Labels, nil +} + +// Dangling returns a bool if the image is "dangling" +func (ci *ContainerImage) Dangling() bool { + return len(ci.Names()) == 0 +} + +// TagImage ... +func (ci *ContainerImage) TagImage(tag string) error { + _, err := iopodman.TagImage().Call(ci.Runtime.Conn, ci.ID(), tag) + return err +} + +// RemoveImage calls varlink to remove an image +func (r *LocalRuntime) RemoveImage(ctx context.Context, img *ContainerImage, force bool) (string, error) { + return iopodman.RemoveImage().Call(r.Conn, img.InputName, force) +} + +// History returns the history of an image and its layers +func (ci *ContainerImage) History(ctx context.Context) ([]*image.History, error) { + var imageHistories []*image.History + + reply, err := iopodman.HistoryImage().Call(ci.Runtime.Conn, ci.InputName) + if err != nil { + return nil, err + } + for _, h := range reply { + created, err := time.ParseInLocation(time.RFC3339, h.Created, time.UTC) + if err != nil { + return nil, err + } + ih := image.History{ + ID: h.Id, + Created: &created, + CreatedBy: h.CreatedBy, + Size: h.Size, + Comment: h.Comment, + } + imageHistories = append(imageHistories, &ih) + } + return imageHistories, nil +} + +// LookupContainer gets basic information about container over a varlink +// connection and then translates it to a *Container +func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { + state, err := r.ContainerState(idOrName) + if err != nil { + return nil, err + } + config := r.Config(idOrName) + if err != nil { + return nil, err + } + + rc := remoteContainer{ + r, + config, + state, + } + + c := Container{ + rc, + } + return &c, nil +} + +func (r *LocalRuntime) GetLatestContainer() (*Container, error) { + return nil, libpod.ErrNotImplemented +} + +// ContainerState returns the "state" of the container. +func (r *LocalRuntime) ContainerState(name string) (*libpod.ContainerState, error) { //no-lint + reply, err := iopodman.ContainerStateData().Call(r.Conn, name) + if err != nil { + return nil, err + } + data := libpod.ContainerState{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, err + +} + +// Config returns a container config +func (r *LocalRuntime) Config(name string) *libpod.ContainerConfig { + // TODO the Spec being returned is not populated. Matt and I could not figure out why. Will defer + // further looking into it for after devconf. + // The libpod function for this has no errors so we are kind of in a tough + // spot here. Logging the errors for now. + reply, err := iopodman.ContainerConfig().Call(r.Conn, name) + if err != nil { + logrus.Error("call to container.config failed") + } + data := libpod.ContainerConfig{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + logrus.Error("failed to unmarshal container inspect data") + } + return &data + +} + +// PruneImages is the wrapper call for a remote-client to prune images +func (r *LocalRuntime) PruneImages(all bool) ([]string, error) { + return iopodman.ImagesPrune().Call(r.Conn, all) +} + +// Export is a wrapper to container export to a tarfile +func (r *LocalRuntime) Export(name string, path string) error { + tempPath, err := iopodman.ExportContainer().Call(r.Conn, name, "") + if err != nil { + return err + } + return r.GetFileFromRemoteHost(tempPath, path, true) +} + +func (r *LocalRuntime) GetFileFromRemoteHost(remoteFilePath, outputPath string, delete bool) error { + outputFile, err := os.Create(outputPath) + if err != nil { + return err + } + defer outputFile.Close() + + writer := bufio.NewWriter(outputFile) + defer writer.Flush() + + reply, err := iopodman.ReceiveFile().Send(r.Conn, varlink.Upgrade, remoteFilePath, delete) + if err != nil { + return err + } + + length, _, err := reply() + if err != nil { + return errors.Wrap(err, "unable to get file length for transfer") + } + + reader := r.Conn.Reader + if _, err := io.CopyN(writer, reader, length); err != nil { + return errors.Wrap(err, "file transer failed") + } + return nil +} + +// Import implements the remote calls required to import a container image to the store +func (r *LocalRuntime) Import(ctx context.Context, source, reference string, changes []string, history string, quiet bool) (string, error) { + // First we send the file to the host + tempFile, err := r.SendFileOverVarlink(source) + if err != nil { + return "", err + } + return iopodman.ImportImage().Call(r.Conn, strings.TrimRight(tempFile, ":"), reference, history, changes, true) +} + +func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) error { + buildOptions := iopodman.BuildOptions{ + AddHosts: options.CommonBuildOpts.AddHost, + CgroupParent: options.CommonBuildOpts.CgroupParent, + CpuPeriod: int64(options.CommonBuildOpts.CPUPeriod), + CpuQuota: options.CommonBuildOpts.CPUQuota, + CpuShares: int64(options.CommonBuildOpts.CPUShares), + CpusetCpus: options.CommonBuildOpts.CPUSetMems, + CpusetMems: options.CommonBuildOpts.CPUSetMems, + Memory: options.CommonBuildOpts.Memory, + MemorySwap: options.CommonBuildOpts.MemorySwap, + ShmSize: options.CommonBuildOpts.ShmSize, + Ulimit: options.CommonBuildOpts.Ulimit, + Volume: options.CommonBuildOpts.Volumes, + } + + buildinfo := iopodman.BuildInfo{ + AdditionalTags: options.AdditionalTags, + Annotations: options.Annotations, + BuildArgs: options.Args, + BuildOptions: buildOptions, + CniConfigDir: options.CNIConfigDir, + CniPluginDir: options.CNIPluginPath, + Compression: string(options.Compression), + DefaultsMountFilePath: options.DefaultMountsFilePath, + Dockerfiles: dockerfiles, + //Err: string(options.Err), + ForceRmIntermediateCtrs: options.ForceRmIntermediateCtrs, + Iidfile: options.IIDFile, + Label: options.Labels, + Layers: options.Layers, + Nocache: options.NoCache, + //Out: + Output: options.Output, + OutputFormat: options.OutputFormat, + PullPolicy: options.PullPolicy.String(), + Quiet: options.Quiet, + RemoteIntermediateCtrs: options.RemoveIntermediateCtrs, + //ReportWriter: + RuntimeArgs: options.RuntimeArgs, + SignaturePolicyPath: options.SignaturePolicyPath, + Squash: options.Squash, + } + // tar the file + outputFile, err := ioutil.TempFile("", "varlink_tar_send") + if err != nil { + return err + } + defer outputFile.Close() + defer os.Remove(outputFile.Name()) + + // Create the tarball of the context dir to a tempfile + if err := utils.TarToFilesystem(options.ContextDirectory, outputFile); err != nil { + return err + } + // Send the context dir tarball over varlink. + tempFile, err := r.SendFileOverVarlink(outputFile.Name()) + if err != nil { + return err + } + buildinfo.ContextDir = tempFile + + reply, err := iopodman.BuildImage().Send(r.Conn, varlink.More, buildinfo) + if err != nil { + return err + } + + for { + responses, flags, err := reply() + if err != nil { + return err + } + for _, line := range responses.Logs { + fmt.Print(line) + } + if flags&varlink.Continues == 0 { + break + } + } + return err +} + +// SendFileOverVarlink sends a file over varlink in an upgraded connection +func (r *LocalRuntime) SendFileOverVarlink(source string) (string, error) { + fs, err := os.Open(source) + if err != nil { + return "", err + } + + fileInfo, err := fs.Stat() + if err != nil { + return "", err + } + logrus.Debugf("sending %s over varlink connection", source) + reply, err := iopodman.SendFile().Send(r.Conn, varlink.Upgrade, "", int64(fileInfo.Size())) + if err != nil { + return "", err + } + _, _, err = reply() + if err != nil { + return "", err + } + + reader := bufio.NewReader(fs) + _, err = reader.WriteTo(r.Conn.Writer) + if err != nil { + return "", err + } + logrus.Debugf("file transfer complete for %s", source) + r.Conn.Writer.Flush() + + // All was sent, wait for the ACK from the server + tempFile, err := r.Conn.Reader.ReadString(':') + if err != nil { + return "", err + } + + // r.Conn is kaput at this point due to the upgrade + if err := r.RemoteRuntime.RefreshConnection(); err != nil { + return "", err + + } + + return strings.Replace(tempFile, ":", "", -1), nil +} + +// GetAllVolumes retrieves all the volumes +func (r *LocalRuntime) GetAllVolumes() ([]*libpod.Volume, error) { + return nil, libpod.ErrNotImplemented +} + +// RemoveVolume removes a volumes +func (r *LocalRuntime) RemoveVolume(ctx context.Context, v *libpod.Volume, force, prune bool) error { + return libpod.ErrNotImplemented +} + +// GetContainers retrieves all containers from the state +// Filters can be provided which will determine what containers are included in +// the output. Multiple filters are handled by ANDing their output, so only +// containers matching all filters are returned +func (r *LocalRuntime) GetContainers(filters ...libpod.ContainerFilter) ([]*libpod.Container, error) { + return nil, libpod.ErrNotImplemented +} + +// RemoveContainer removes the given container +// If force is specified, the container will be stopped first +// Otherwise, RemoveContainer will return an error if the container is running +func (r *LocalRuntime) RemoveContainer(ctx context.Context, c *libpod.Container, force, volumes bool) error { + return libpod.ErrNotImplemented +} + +// CreateVolume creates a volume over a varlink connection for the remote client +func (r *LocalRuntime) CreateVolume(ctx context.Context, c *cliconfig.VolumeCreateValues, labels, opts map[string]string) (string, error) { + cvOpts := iopodman.VolumeCreateOpts{ + Options: opts, + Labels: labels, + } + if len(c.InputArgs) > 0 { + cvOpts.VolumeName = c.InputArgs[0] + } + + if c.Flag("driver").Changed { + cvOpts.Driver = c.Driver + } + + return iopodman.VolumeCreate().Call(r.Conn, cvOpts) +} + +// RemoveVolumes removes volumes over a varlink connection for the remote client +func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmValues) ([]string, error) { + rmOpts := iopodman.VolumeRemoveOpts{ + All: c.All, + Force: c.Force, + Volumes: c.InputArgs, + } + return iopodman.VolumeRemove().Call(r.Conn, rmOpts) +} + +func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { + + var ( + tls *bool + tlsVerify bool + ) + if dockerRegistryOptions.DockerInsecureSkipTLSVerify == types.OptionalBoolTrue { + tlsVerify = false + tls = &tlsVerify + } + if dockerRegistryOptions.DockerInsecureSkipTLSVerify == types.OptionalBoolFalse { + tlsVerify = true + tls = &tlsVerify + } + + reply, err := iopodman.PushImage().Send(r.Conn, varlink.More, srcName, destination, tls, signaturePolicyPath, "", dockerRegistryOptions.DockerCertPath, forceCompress, manifestMIMEType, signingOptions.RemoveSignatures, signingOptions.SignBy) + if err != nil { + return err + } + for { + responses, flags, err := reply() + if err != nil { + return err + } + for _, line := range responses.Logs { + fmt.Print(line) + } + if flags&varlink.Continues == 0 { + break + } + } + + return err +} + +// InspectVolumes returns a slice of volumes based on an arg list or --all +func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*Volume, error) { + reply, err := iopodman.GetVolumes().Call(r.Conn, c.InputArgs, c.All) + if err != nil { + return nil, err + } + return varlinkVolumeToVolume(r, reply), nil +} + +//Volumes returns a slice of adapter.volumes based on information about libpod +// volumes over a varlink connection +func (r *LocalRuntime) Volumes(ctx context.Context) ([]*Volume, error) { + reply, err := iopodman.GetVolumes().Call(r.Conn, []string{}, true) + if err != nil { + return nil, err + } + return varlinkVolumeToVolume(r, reply), nil +} + +func varlinkVolumeToVolume(r *LocalRuntime, volumes []iopodman.Volume) []*Volume { + var vols []*Volume + for _, v := range volumes { + volumeConfig := libpod.VolumeConfig{ + Name: v.Name, + Labels: v.Labels, + MountPoint: v.MountPoint, + Driver: v.Driver, + Options: v.Options, + Scope: v.Scope, + } + n := remoteVolume{ + Runtime: r, + config: &volumeConfig, + } + newVol := Volume{ + n, + } + vols = append(vols, &newVol) + } + return vols +} + +// PruneVolumes removes all unused volumes from the remote system +func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) { + var errs []error + prunedNames, prunedErrors, err := iopodman.VolumesPrune().Call(r.Conn) + if err != nil { + return []string{}, []error{err} + } + // We need to transform the string results of the error into actual error types + for _, e := range prunedErrors { + errs = append(errs, errors.New(e)) + } + return prunedNames, errs +} + +// SaveImage is a wrapper function for saving an image to the local filesystem +func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) error { + source := c.InputArgs[0] + additionalTags := c.InputArgs[1:] + + options := iopodman.ImageSaveOptions{ + Name: source, + Format: c.Format, + Output: c.Output, + MoreTags: additionalTags, + Quiet: c.Quiet, + Compress: c.Compress, + } + reply, err := iopodman.ImageSave().Send(r.Conn, varlink.More, options) + if err != nil { + return err + } + + var fetchfile string + for { + responses, flags, err := reply() + if err != nil { + return err + } + if len(responses.Id) > 0 { + fetchfile = responses.Id + } + for _, line := range responses.Logs { + fmt.Print(line) + } + if flags&varlink.Continues == 0 { + break + } + + } + if err != nil { + return err + } + + outputToDir := false + outfile := c.Output + var outputFile *os.File + // If the result is supposed to be a dir, then we need to put the tarfile + // from the host in a temporary file + if options.Format != "oci-archive" && options.Format != "docker-archive" { + outputToDir = true + outputFile, err = ioutil.TempFile("", "saveimage_tempfile") + if err != nil { + return err + } + outfile = outputFile.Name() + defer outputFile.Close() + defer os.Remove(outputFile.Name()) + } + // We now need to fetch the tarball result back to the more system + if err := r.GetFileFromRemoteHost(fetchfile, outfile, true); err != nil { + return err + } + + // If the result is a tarball, we're done + // If it is a dir, we need to untar the temporary file into the dir + if outputToDir { + if err := utils.UntarToFileSystem(c.Output, outputFile, &archive.TarOptions{}); err != nil { + return err + } + } + return nil +} + +// LoadImage loads a container image from a remote client's filesystem +func (r *LocalRuntime) LoadImage(ctx context.Context, name string, cli *cliconfig.LoadValues) (string, error) { + var names string + remoteTempFile, err := r.SendFileOverVarlink(cli.Input) + if err != nil { + return "", nil + } + more := varlink.More + if cli.Quiet { + more = 0 + } + reply, err := iopodman.LoadImage().Send(r.Conn, uint64(more), name, remoteTempFile, cli.Quiet, true) + if err != nil { + return "", err + } + + for { + responses, flags, err := reply() + if err != nil { + logrus.Error(err) + return "", err + } + for _, line := range responses.Logs { + fmt.Print(line) + } + names = responses.Id + if flags&varlink.Continues == 0 { + break + } + } + return names, nil +} diff --git a/pkg/adapter/shortcuts/shortcuts.go b/pkg/adapter/shortcuts/shortcuts.go new file mode 100644 index 000000000..0633399ae --- /dev/null +++ b/pkg/adapter/shortcuts/shortcuts.go @@ -0,0 +1,27 @@ +package shortcuts + +import "github.com/containers/libpod/libpod" + +// GetPodsByContext gets pods whether all, latest, or a slice of names/ids +func GetPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) ([]*libpod.Pod, error) { + var outpods []*libpod.Pod + if all { + return runtime.GetAllPods() + } + if latest { + p, err := runtime.GetLatestPod() + if err != nil { + return nil, err + } + outpods = append(outpods, p) + return outpods, nil + } + for _, p := range pods { + pod, err := runtime.LookupPod(p) + if err != nil { + return nil, err + } + outpods = append(outpods, pod) + } + return outpods, nil +} diff --git a/pkg/adapter/volumes_remote.go b/pkg/adapter/volumes_remote.go new file mode 100644 index 000000000..beacd943a --- /dev/null +++ b/pkg/adapter/volumes_remote.go @@ -0,0 +1,33 @@ +// +build remoteclient + +package adapter + +// Name returns the name of the volume +func (v *Volume) Name() string { + return v.config.Name +} + +//Labels returns the labels for a volume +func (v *Volume) Labels() map[string]string { + return v.config.Labels +} + +// Driver returns the driver for the volume +func (v *Volume) Driver() string { + return v.config.Driver +} + +// Options returns the options a volume was created with +func (v *Volume) Options() map[string]string { + return v.config.Options +} + +// MountPath returns the path the volume is mounted to +func (v *Volume) MountPoint() string { + return v.config.MountPoint +} + +// Scope returns the scope for an adapter.volume +func (v *Volume) Scope() string { + return v.config.Scope +} diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go index 2988c5d84..a343bfd53 100644 --- a/pkg/varlinkapi/pods.go +++ b/pkg/varlinkapi/pods.go @@ -2,7 +2,7 @@ package varlinkapi import ( "encoding/json" - "github.com/containers/libpod/libpod/adapter/shortcuts" + "github.com/containers/libpod/pkg/adapter/shortcuts" "github.com/containers/libpod/pkg/rootless" "syscall" diff --git a/test/e2e/pod_start_test.go b/test/e2e/pod_start_test.go index 77e8b586d..ce693012d 100644 --- a/test/e2e/pod_start_test.go +++ b/test/e2e/pod_start_test.go @@ -136,6 +136,5 @@ var _ = Describe("Podman pod start", func() { session = podmanTest.Podman([]string{"pod", "start", podid, "doesnotexist"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(125)) - Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) }) }) diff --git a/test/e2e/pod_stop_test.go b/test/e2e/pod_stop_test.go index b3d7df252..38f118964 100644 --- a/test/e2e/pod_stop_test.go +++ b/test/e2e/pod_stop_test.go @@ -137,6 +137,5 @@ var _ = Describe("Podman pod stop", func() { session = podmanTest.Podman([]string{"pod", "stop", podid1, "doesnotexist"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(125)) - Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) }) }) -- cgit v1.2.3-54-g00ecf