diff options
author | baude <bbaude@redhat.com> | 2019-04-15 09:03:18 -0500 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2019-04-18 13:42:27 -0500 |
commit | 55e630e7876557ebd2a44e81fa357aab9efbb793 (patch) | |
tree | cc8b6f224a6520e3c38bc41022abe40c6f1952a2 | |
parent | bf5ffdafb40f32fac891a8cd5fc64cfd5b77674f (diff) | |
download | podman-55e630e7876557ebd2a44e81fa357aab9efbb793.tar.gz podman-55e630e7876557ebd2a44e81fa357aab9efbb793.tar.bz2 podman-55e630e7876557ebd2a44e81fa357aab9efbb793.zip |
podman-remote pause|unpause
Add the ability to pause and unpause containers with the remote client.
Also turned on the pause tests!
Signed-off-by: baude <bbaude@redhat.com>
-rw-r--r-- | cmd/podman/commands.go | 4 | ||||
-rw-r--r-- | cmd/podman/container.go | 2 | ||||
-rw-r--r-- | cmd/podman/main.go | 2 | ||||
-rw-r--r-- | cmd/podman/pause.go | 54 | ||||
-rw-r--r-- | cmd/podman/ps.go | 6 | ||||
-rw-r--r-- | cmd/podman/unpause.go | 54 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 2 | ||||
-rw-r--r-- | contrib/cirrus/container_test.sh | 8 | ||||
-rwxr-xr-x | contrib/cirrus/integration_test.sh | 2 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 87 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 110 | ||||
-rw-r--r-- | pkg/varlinkapi/containers.go | 31 | ||||
-rw-r--r-- | test/e2e/common_test.go | 168 | ||||
-rw-r--r-- | test/e2e/libpod_suite_remoteclient_test.go | 109 | ||||
-rw-r--r-- | test/e2e/libpod_suite_test.go | 168 | ||||
-rw-r--r-- | test/e2e/pause_test.go | 3 | ||||
-rw-r--r-- | test/utils/utils.go | 6 |
17 files changed, 452 insertions, 364 deletions
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index 1a2da86cf..c36452cfe 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -17,14 +17,12 @@ func getMainCommands() []*cobra.Command { _loginCommand, _logoutCommand, _mountCommand, - _pauseCommand, _portCommand, _refreshCommand, _restartCommand, _searchCommand, _statsCommand, _topCommand, - _unpauseCommand, } if len(_varlinkCommand.Use) > 0 { @@ -49,7 +47,6 @@ func getContainerSubCommands() []*cobra.Command { _commitCommand, _execCommand, _mountCommand, - _pauseCommand, _portCommand, _pruneContainersCommand, _refreshCommand, @@ -60,7 +57,6 @@ func getContainerSubCommands() []*cobra.Command { _stopCommand, _topCommand, _umountCommand, - _unpauseCommand, } } diff --git a/cmd/podman/container.go b/cmd/podman/container.go index 1477d158f..7733c8eef 100644 --- a/cmd/podman/container.go +++ b/cmd/podman/container.go @@ -59,9 +59,11 @@ var ( _killCommand, _listSubCommand, _logsCommand, + _pauseCommand, _runCommand, _rmCommand, _startCommand, + _unpauseCommand, _waitCommand, } ) diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 2748df5f5..15f4a5d71 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -45,6 +45,7 @@ var mainCommands = []*cobra.Command{ _killCommand, _loadCommand, _logsCommand, + _pauseCommand, podCommand.Command, &_psCommand, _pullCommand, @@ -56,6 +57,7 @@ var mainCommands = []*cobra.Command{ _stopCommand, _tagCommand, _umountCommand, + _unpauseCommand, _versionCommand, _waitCommand, imageCommand.Command, diff --git a/cmd/podman/pause.go b/cmd/podman/pause.go index 3e6d36571..ca137150a 100644 --- a/cmd/podman/pause.go +++ b/cmd/podman/pause.go @@ -4,11 +4,9 @@ import ( "os" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -41,15 +39,11 @@ func init() { } func pauseCmd(c *cliconfig.PauseValues) error { - var ( - pauseContainers []*libpod.Container - pauseFuncs []shared.ParallelWorkerInput - ) if os.Geteuid() != 0 { return errors.New("pause is not supported for rootless containers") } - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } @@ -59,41 +53,19 @@ func pauseCmd(c *cliconfig.PauseValues) error { if len(args) < 1 && !c.All { return errors.Errorf("you must provide at least one container name or id") } - if c.All { - containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running") - if err != nil { - return err - } - pauseContainers = append(pauseContainers, containers...) - } else { - for _, arg := range args { - ctr, err := runtime.LookupContainer(arg) - if err != nil { - return err + ok, failures, err := runtime.PauseContainers(getContext(), c) + if err != nil { + if errors.Cause(err) == libpod.ErrNoSuchCtr { + if len(c.InputArgs) > 1 { + exitCode = 125 + } else { + exitCode = 1 } - pauseContainers = append(pauseContainers, ctr) - } - } - - // Now assemble the slice of pauseFuncs - for _, ctr := range pauseContainers { - con := ctr - - f := func() error { - return con.Pause() } - pauseFuncs = append(pauseFuncs, shared.ParallelWorkerInput{ - ContainerID: con.ID(), - ParallelFunc: f, - }) + return err } - - maxWorkers := shared.Parallelize("pause") - if c.GlobalIsSet("max-workers") { - maxWorkers = c.GlobalFlags.MaxWorks + if len(failures) > 0 { + exitCode = 125 } - logrus.Debugf("Setting maximum workers to %d", maxWorkers) - - pauseErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, pauseFuncs) - return printParallelOutput(pauseErrors, errCount) + return printCmdResults(ok, failures) } diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index a9e46d6b9..df1ea2765 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -17,7 +17,6 @@ import ( "github.com/containers/libpod/pkg/adapter" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/go-units" - "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/fields" @@ -198,11 +197,6 @@ func init() { } func psCmd(c *cliconfig.PsValues) error { - if c.Bool("trace") { - span, _ := opentracing.StartSpanFromContext(Ctx, "psCmd") - defer span.Finish() - } - var watch bool if c.Watch > 0 { diff --git a/cmd/podman/unpause.go b/cmd/podman/unpause.go index 65e841b36..fa946bfd7 100644 --- a/cmd/podman/unpause.go +++ b/cmd/podman/unpause.go @@ -4,11 +4,9 @@ import ( "os" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -40,15 +38,11 @@ func init() { } func unpauseCmd(c *cliconfig.UnpauseValues) error { - var ( - unpauseContainers []*libpod.Container - unpauseFuncs []shared.ParallelWorkerInput - ) if os.Geteuid() != 0 { return errors.New("unpause is not supported for rootless containers") } - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } @@ -58,41 +52,19 @@ func unpauseCmd(c *cliconfig.UnpauseValues) error { if len(args) < 1 && !c.All { return errors.Errorf("you must provide at least one container name or id") } - if c.All { - cs, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStatePaused, "paused") - if err != nil { - return err - } - unpauseContainers = append(unpauseContainers, cs...) - } else { - for _, arg := range args { - ctr, err := runtime.LookupContainer(arg) - if err != nil { - return err + ok, failures, err := runtime.UnpauseContainers(getContext(), c) + if err != nil { + if errors.Cause(err) == libpod.ErrNoSuchCtr { + if len(c.InputArgs) > 1 { + exitCode = 125 + } else { + exitCode = 1 } - unpauseContainers = append(unpauseContainers, ctr) - } - } - - // Assemble the unpause funcs - for _, ctr := range unpauseContainers { - con := ctr - f := func() error { - return con.Unpause() } - - unpauseFuncs = append(unpauseFuncs, shared.ParallelWorkerInput{ - ContainerID: con.ID(), - ParallelFunc: f, - }) + return err } - - maxWorkers := shared.Parallelize("unpause") - if c.GlobalIsSet("max-workers") { - maxWorkers = c.GlobalFlags.MaxWorks + if len(failures) > 0 { + exitCode = 125 } - logrus.Debugf("Setting maximum workers to %d", maxWorkers) - - unpauseErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, unpauseFuncs) - return printParallelOutput(unpauseErrors, errCount) + return printCmdResults(ok, failures) } diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 497f130bc..1fde72164 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -522,6 +522,8 @@ method ListContainers() -> (containers: []Container) method Ps(opts: PsOpts) -> (containers: []PsContainer) +method GetContainersByStatus(status: []string) -> (containerS: []Container) + # GetContainer returns information about a single container. If a container # with the given id doesn't exist, a [ContainerNotFound](#ContainerNotFound) # error will be returned. See also [ListContainers](ListContainers) and diff --git a/contrib/cirrus/container_test.sh b/contrib/cirrus/container_test.sh index e6c1a3a47..1fd9551db 100644 --- a/contrib/cirrus/container_test.sh +++ b/contrib/cirrus/container_test.sh @@ -32,6 +32,7 @@ integrationtest=0 unittest=0 validate=0 options=0 +noremote=0 install_tools_made=0 while getopts "biptuv" opt; do @@ -45,6 +46,9 @@ while getopts "biptuv" opt; do t) integrationtest=1 options=1 ;; + n) noremote=1 + options=1 + ;; u) unittest=1 options=1 ;; @@ -127,5 +131,7 @@ if [ $integrationtest -eq 1 ]; then make TAGS="${TAGS}" test-binaries make varlink_generate make ginkgo $INTEGRATION_TEST_ENVS - make ginkgo-remote $INTEGRATION_TEST_ENVS + if [ $noremote -eq 0 ]; then + make ginkgo-remote $INTEGRATION_TEST_ENVS + fi fi diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh index 8a2507f38..95387ff49 100755 --- a/contrib/cirrus/integration_test.sh +++ b/contrib/cirrus/integration_test.sh @@ -34,7 +34,7 @@ then -e "CONMON_BINARY=/usr/libexec/podman/conmon" \ -e "DIST=$OS_RELEASE_ID" \ -e "CONTAINER_RUNTIME=$CONTAINER_RUNTIME" \ - ${OS_RELEASE_ID}podmanbuild bash $GOSRC/$SCRIPT_BASE/container_test.sh -b -i -t + ${OS_RELEASE_ID}podmanbuild bash $GOSRC/$SCRIPT_BASE/container_test.sh -b -i -t -n exit $? elif [[ "$SPECIALMODE" == "rootless" ]] diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 063ecfbfb..5279f11b2 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -607,3 +607,90 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP } return exitCode, lastError } + +// PauseContainers removes container(s) based on CLI inputs. +func (r *LocalRuntime) PauseContainers(ctx context.Context, cli *cliconfig.PauseValues) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ctrs []*libpod.Container + err error + ) + + maxWorkers := shared.DefaultPoolSize("pause") + if cli.GlobalIsSet("max-workers") { + maxWorkers = cli.GlobalFlags.MaxWorks + } + logrus.Debugf("Setting maximum rm workers to %d", maxWorkers) + + if cli.All { + ctrs, err = r.GetRunningContainers() + } else { + ctrs, err = shortcuts.GetContainersByContext(false, false, cli.InputArgs, r.Runtime) + } + if err != nil { + return ok, failures, err + } + + pool := shared.NewPool("pause", maxWorkers, len(ctrs)) + for _, c := range ctrs { + ctr := c + pool.Add(shared.Job{ + ID: ctr.ID(), + Fn: func() error { + err := ctr.Pause() + if err != nil { + logrus.Debugf("Failed to pause container %s: %s", ctr.ID(), err.Error()) + } + return err + }, + }) + } + return pool.Run() +} + +// UnpauseContainers removes container(s) based on CLI inputs. +func (r *LocalRuntime) UnpauseContainers(ctx context.Context, cli *cliconfig.UnpauseValues) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ctrs []*libpod.Container + err error + ) + + maxWorkers := shared.DefaultPoolSize("pause") + if cli.GlobalIsSet("max-workers") { + maxWorkers = cli.GlobalFlags.MaxWorks + } + logrus.Debugf("Setting maximum rm workers to %d", maxWorkers) + + if cli.All { + var filterFuncs []libpod.ContainerFilter + filterFuncs = append(filterFuncs, func(c *libpod.Container) bool { + state, _ := c.State() + return state == libpod.ContainerStatePaused + }) + ctrs, err = r.GetContainers(filterFuncs...) + } else { + ctrs, err = shortcuts.GetContainersByContext(false, false, cli.InputArgs, r.Runtime) + } + if err != nil { + return ok, failures, err + } + + pool := shared.NewPool("pause", maxWorkers, len(ctrs)) + for _, c := range ctrs { + ctr := c + pool.Add(shared.Job{ + ID: ctr.ID(), + Fn: func() error { + err := ctr.Unpause() + if err != nil { + logrus.Debugf("Failed to unpause container %s: %s", ctr.ID(), err.Error()) + } + return err + }, + }) + } + return pool.Run() +} diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index d5314c382..cb61871bf 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -45,6 +45,18 @@ func (c *Container) ID() string { return c.config.ID } +// Pause a container +func (c *Container) Pause() error { + _, err := iopodman.PauseContainer().Call(c.Runtime.Conn, c.ID()) + return err +} + +// Unpause a container +func (c *Container) Unpause() error { + _, err := iopodman.UnpauseContainer().Call(c.Runtime.Conn, c.ID()) + return 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 @@ -90,6 +102,19 @@ func (r *LocalRuntime) Spec(name string) (*specs.Spec, error) { return &data, nil } +// LookupContainers is a wrapper for LookupContainer +func (r *LocalRuntime) LookupContainers(idsOrNames []string) ([]*Container, error) { + var containers []*Container + for _, name := range idsOrNames { + ctr, err := r.LookupContainer(name) + if err != nil { + return nil, err + } + containers = append(containers, ctr) + } + return containers, 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) { @@ -107,6 +132,24 @@ func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { }, nil } +func (r *LocalRuntime) LookupContainersWithStatus(filters []string) ([]*Container, error) { + var containers []*Container + ctrs, err := iopodman.GetContainersByStatus().Call(r.Conn, filters) + if err != nil { + return nil, err + } + // This is not performance savy; if this turns out to be a problematic series of lookups, we need to + // create a new endpoint to speed things up + for _, ctr := range ctrs { + container, err := r.LookupContainer(ctr.Id) + if err != nil { + return nil, err + } + containers = append(containers, container) + } + return containers, nil +} + func (r *LocalRuntime) GetLatestContainer() (*Container, error) { reply, err := iopodman.GetContainersByContext().Call(r.Conn, false, true, nil) if err != nil { @@ -643,3 +686,70 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP } return exitCode, finalErr } + +// PauseContainers pauses container(s) based on CLI inputs. +func (r *LocalRuntime) PauseContainers(ctx context.Context, cli *cliconfig.PauseValues) ([]string, map[string]error, error) { + var ( + ok []string + failures = map[string]error{} + ctrs []*Container + err error + ) + + if cli.All { + filters := []string{libpod.ContainerStateRunning.String()} + ctrs, err = r.LookupContainersWithStatus(filters) + } else { + ctrs, err = r.LookupContainers(cli.InputArgs) + } + if err != nil { + return ok, failures, err + } + + for _, c := range ctrs { + c := c + err := c.Pause() + if err != nil { + failures[c.ID()] = err + } else { + ok = append(ok, c.ID()) + } + } + return ok, failures, nil +} + +// UnpauseContainers unpauses containers based on input +func (r *LocalRuntime) UnpauseContainers(ctx context.Context, cli *cliconfig.UnpauseValues) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ctrs []*Container + err error + ) + + maxWorkers := shared.DefaultPoolSize("unpause") + if cli.GlobalIsSet("max-workers") { + maxWorkers = cli.GlobalFlags.MaxWorks + } + logrus.Debugf("Setting maximum rm workers to %d", maxWorkers) + + if cli.All { + filters := []string{libpod.ContainerStatePaused.String()} + ctrs, err = r.LookupContainersWithStatus(filters) + } else { + ctrs, err = r.LookupContainers(cli.InputArgs) + } + if err != nil { + return ok, failures, err + } + for _, c := range ctrs { + c := c + err := c.Unpause() + if err != nil { + failures[c.ID()] = err + } else { + ok = append(ok, c.ID()) + } + } + return ok, failures, nil +} diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index 17792ccfe..237407050 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -128,6 +128,37 @@ func (i *LibpodAPI) GetContainersByContext(call iopodman.VarlinkCall, all, lates return call.ReplyGetContainersByContext(ids) } +// GetContainersByStatus returns a slice of containers filtered by a libpod status +func (i *LibpodAPI) GetContainersByStatus(call iopodman.VarlinkCall, statuses []string) error { + var ( + filterFuncs []libpod.ContainerFilter + containers []iopodman.Container + ) + for _, status := range statuses { + lpstatus, err := libpod.StringToContainerStatus(status) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + filterFuncs = append(filterFuncs, func(c *libpod.Container) bool { + state, _ := c.State() + return state == lpstatus + }) + } + filteredContainers, err := i.Runtime.GetContainers(filterFuncs...) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + opts := shared.PsOptions{Size: true, Namespace: true} + for _, ctr := range filteredContainers { + batchInfo, err := shared.BatchContainerOp(ctr, opts) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + containers = append(containers, makeListContainer(ctr.ID(), batchInfo)) + } + return call.ReplyGetContainersByStatus(containers) +} + // InspectContainer ... func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) error { ctr, err := i.Runtime.LookupContainer(name) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 58f94f27e..a30a9b20b 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -11,14 +11,16 @@ import ( "strings" "testing" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/storage" - + "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/inspect" + "github.com/containers/libpod/pkg/rootless" . "github.com/containers/libpod/test/utils" + "github.com/containers/storage" "github.com/containers/storage/pkg/reexec" + "github.com/containers/storage/pkg/stringid" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/onsi/gomega/gexec" ) var ( @@ -262,6 +264,10 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { } if remote { p.PodmanTest.RemotePodmanBinary = podmanRemoteBinary + if !rootless.IsRootless() { + uuid := stringid.GenerateNonCryptoID() + p.VarlinkEndpoint = fmt.Sprintf("unix:/run/podman/io.podman-%s", uuid) + } } // Setup registries.conf ENV variable @@ -337,3 +343,159 @@ func GetPortLock(port string) storage.Locker { lock.Lock() return lock } + +// RunTopContainer runs a simple container in the background that +// runs top. If the name passed != "", it will have a name +func (p *PodmanTestIntegration) RunTopContainer(name string) *PodmanSessionIntegration { + var podmanArgs = []string{"run"} + if name != "" { + podmanArgs = append(podmanArgs, "--name", name) + } + podmanArgs = append(podmanArgs, "-d", ALPINE, "top") + return p.Podman(podmanArgs) +} + +// RunLsContainer runs a simple container in the background that +// simply runs ls. If the name passed != "", it will have a name +func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionIntegration, int, string) { + var podmanArgs = []string{"run"} + if name != "" { + podmanArgs = append(podmanArgs, "--name", name) + } + podmanArgs = append(podmanArgs, "-d", ALPINE, "ls") + session := p.Podman(podmanArgs) + session.WaitWithDefaultTimeout() + return session, session.ExitCode(), session.OutputToString() +} + +func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) { + var podmanArgs = []string{"run", "--pod", pod} + if name != "" { + podmanArgs = append(podmanArgs, "--name", name) + } + podmanArgs = append(podmanArgs, "-d", ALPINE, "ls") + session := p.Podman(podmanArgs) + session.WaitWithDefaultTimeout() + return session, session.ExitCode(), session.OutputToString() +} + +// BuildImage uses podman build and buildah to build an image +// called imageName based on a string dockerfile +func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) { + dockerfilePath := filepath.Join(p.TempDir, "Dockerfile") + err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755) + Expect(err).To(BeNil()) + session := p.Podman([]string{"build", "--layers=" + layers, "-t", imageName, "--file", dockerfilePath, p.TempDir}) + session.Wait(120) + Expect(session.ExitCode()).To(Equal(0)) +} + +// PodmanPID execs podman and returns its PID +func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) { + podmanOptions := p.MakeOptions(args) + fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) + command := exec.Command(p.PodmanBinary, podmanOptions...) + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + if err != nil { + Fail(fmt.Sprintf("unable to run podman command: %s", strings.Join(podmanOptions, " "))) + } + podmanSession := &PodmanSession{session} + return &PodmanSessionIntegration{podmanSession}, command.Process.Pid +} + +// Cleanup cleans up the temporary store +func (p *PodmanTestIntegration) Cleanup() { + // Remove all containers + stopall := p.Podman([]string{"stop", "-a", "--timeout", "0"}) + // stopall.WaitWithDefaultTimeout() + stopall.Wait(90) + + session := p.Podman([]string{"rm", "-fa"}) + session.Wait(90) + + p.StopVarlink() + // Nuke tempdir + if err := os.RemoveAll(p.TempDir); err != nil { + fmt.Printf("%q\n", err) + } + + // Clean up the registries configuration file ENV variable set in Create + resetRegistriesConfigEnv() +} + +// CleanupPod cleans up the temporary store +func (p *PodmanTestIntegration) CleanupPod() { + // Remove all containers + session := p.Podman([]string{"pod", "rm", "-fa"}) + session.Wait(90) + // Nuke tempdir + if err := os.RemoveAll(p.TempDir); err != nil { + fmt.Printf("%q\n", err) + } +} + +// CleanupVolume cleans up the temporary store +func (p *PodmanTestIntegration) CleanupVolume() { + // Remove all containers + session := p.Podman([]string{"volume", "rm", "-fa"}) + session.Wait(90) + // Nuke tempdir + if err := os.RemoveAll(p.TempDir); err != nil { + fmt.Printf("%q\n", err) + } +} + +// PullImages pulls multiple images +func (p *PodmanTestIntegration) PullImages(images []string) error { + for _, i := range images { + p.PullImage(i) + } + return nil +} + +// PullImage pulls a single image +// TODO should the timeout be configurable? +func (p *PodmanTestIntegration) PullImage(image string) error { + session := p.Podman([]string{"pull", image}) + session.Wait(60) + Expect(session.ExitCode()).To(Equal(0)) + return nil +} + +// InspectContainerToJSON takes the session output of an inspect +// container and returns json +func (s *PodmanSessionIntegration) InspectContainerToJSON() []inspect.ContainerData { + var i []inspect.ContainerData + err := json.Unmarshal(s.Out.Contents(), &i) + Expect(err).To(BeNil()) + return i +} + +// InspectPodToJSON takes the sessions output from a pod inspect and returns json +func (s *PodmanSessionIntegration) InspectPodToJSON() libpod.PodInspect { + var i libpod.PodInspect + err := json.Unmarshal(s.Out.Contents(), &i) + Expect(err).To(BeNil()) + return i +} + +// CreatePod creates a pod with no infra container +// it optionally takes a pod name +func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegration, int, string) { + var podmanArgs = []string{"pod", "create", "--infra=false", "--share", ""} + if name != "" { + podmanArgs = append(podmanArgs, "--name", name) + } + session := p.Podman(podmanArgs) + session.WaitWithDefaultTimeout() + return session, session.ExitCode(), session.OutputToString() +} + +func (p *PodmanTestIntegration) RunTopContainerInPod(name, pod string) *PodmanSessionIntegration { + var podmanArgs = []string{"run", "--pod", pod} + if name != "" { + podmanArgs = append(podmanArgs, "--name", name) + } + podmanArgs = append(podmanArgs, "-d", ALPINE, "top") + return p.Podman(podmanArgs) +} diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go index a85d21a48..1e477fe2f 100644 --- a/test/e2e/libpod_suite_remoteclient_test.go +++ b/test/e2e/libpod_suite_remoteclient_test.go @@ -4,14 +4,14 @@ package integration import ( "fmt" - "github.com/containers/libpod/libpod" - "github.com/containers/libpod/pkg/inspect" - "github.com/onsi/ginkgo" + "github.com/containers/libpod/pkg/rootless" "io/ioutil" "os" "os/exec" "path/filepath" "strings" + + "github.com/onsi/ginkgo" ) func SkipIfRemote() { @@ -24,48 +24,12 @@ func SkipIfRootless() { } } -// Cleanup cleans up the temporary store -func (p *PodmanTestIntegration) Cleanup() { - p.StopVarlink() - // TODO - // Stop all containers - // Rm all containers - - if err := os.RemoveAll(p.TempDir); err != nil { - fmt.Printf("%q\n", err) - } - - // Clean up the registries configuration file ENV variable set in Create - resetRegistriesConfigEnv() -} - // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { podmanSession := p.PodmanBase(args) return &PodmanSessionIntegration{podmanSession} } -//RunTopContainer runs a simple container in the background that -// runs top. If the name passed != "", it will have a name -func (p *PodmanTestIntegration) RunTopContainer(name string) *PodmanSessionIntegration { - // TODO - return nil -} - -//RunLsContainer runs a simple container in the background that -// simply runs ls. If the name passed != "", it will have a name -func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionIntegration, int, string) { - // TODO - return nil, 0, "" -} - -// InspectImageJSON takes the session output of an inspect -// image and returns json -//func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { -// // TODO -// return nil -//} - func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() { defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf") os.Setenv("REGISTRIES_CONFIG_PATH", defaultFile) @@ -80,64 +44,6 @@ func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) { func resetRegistriesConfigEnv() { os.Setenv("REGISTRIES_CONFIG_PATH", "") } - -// InspectContainerToJSON takes the session output of an inspect -// container and returns json -func (s *PodmanSessionIntegration) InspectContainerToJSON() []inspect.ContainerData { - // TODO - return nil -} - -// CreatePod creates a pod with no infra container -// it optionally takes a pod name -func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegration, int, string) { - // TODO - return nil, 0, "" -} - -func (p *PodmanTestIntegration) RunTopContainerInPod(name, pod string) *PodmanSessionIntegration { - // TODO - return nil -} - -// BuildImage uses podman build and buildah to build an image -// called imageName based on a string dockerfile -func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) { - // TODO -} - -// CleanupPod cleans up the temporary store -func (p *PodmanTestIntegration) CleanupPod() { - // TODO -} - -// InspectPodToJSON takes the sessions output from a pod inspect and returns json -func (s *PodmanSessionIntegration) InspectPodToJSON() libpod.PodInspect { - // TODO - return libpod.PodInspect{} -} -func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) { - // TODO - return nil, 0, "" -} - -// PullImages pulls multiple images -func (p *PodmanTestIntegration) PullImages(images []string) error { - // TODO - return libpod.ErrNotImplemented -} - -// PodmanPID execs podman and returns its PID -func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) { - // TODO - return nil, 0 -} - -// CleanupVolume cleans up the temporary store -func (p *PodmanTestIntegration) CleanupVolume() { - // TODO -} - func PodmanTestCreate(tempDir string) *PodmanTestIntegration { pti := PodmanTestCreateUtil(tempDir, true) pti.StartVarlink() @@ -148,7 +54,7 @@ func (p *PodmanTestIntegration) StartVarlink() { if os.Geteuid() == 0 { os.MkdirAll("/run/podman", 0755) } - varlinkEndpoint := "unix:/run/podman/io.podman" + varlinkEndpoint := p.VarlinkEndpoint if addr := os.Getenv("PODMAN_VARLINK_ADDRESS"); addr != "" { varlinkEndpoint = addr } @@ -165,6 +71,13 @@ func (p *PodmanTestIntegration) StopVarlink() { varlinkSession := p.VarlinkSession varlinkSession.Kill() varlinkSession.Wait() + + if !rootless.IsRootless() { + socket := strings.Split(p.VarlinkEndpoint, ":")[1] + if err := os.Remove(socket); err != nil { + fmt.Println(err) + } + } } //MakeOptions assembles all the podman main options diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index a69c1ba9a..867844c32 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -3,27 +3,17 @@ package integration import ( - "encoding/json" "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" "strings" - "github.com/containers/libpod/libpod" - "github.com/containers/libpod/pkg/inspect" - . "github.com/containers/libpod/test/utils" "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/onsi/gomega/gexec" ) func SkipIfRemote() { - if os.Geteuid() != 0 { - ginkgo.Skip("This function is not enabled for rootless podman") - } + ginkgo.Skip("This function is not enabled for remote podman") } func SkipIfRootless() { @@ -44,161 +34,6 @@ func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd return &PodmanSessionIntegration{podmanSession} } -// PodmanPID execs podman and returns its PID -func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) { - podmanOptions := p.MakeOptions(args) - fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) - command := exec.Command(p.PodmanBinary, podmanOptions...) - session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) - if err != nil { - Fail(fmt.Sprintf("unable to run podman command: %s", strings.Join(podmanOptions, " "))) - } - podmanSession := &PodmanSession{session} - return &PodmanSessionIntegration{podmanSession}, command.Process.Pid -} - -// Cleanup cleans up the temporary store -func (p *PodmanTestIntegration) Cleanup() { - // Remove all containers - stopall := p.Podman([]string{"stop", "-a", "--timeout", "0"}) - // stopall.WaitWithDefaultTimeout() - stopall.Wait(90) - - session := p.Podman([]string{"rm", "-fa"}) - session.Wait(90) - - // Nuke tempdir - if err := os.RemoveAll(p.TempDir); err != nil { - fmt.Printf("%q\n", err) - } - - // Clean up the registries configuration file ENV variable set in Create - resetRegistriesConfigEnv() -} - -// CleanupPod cleans up the temporary store -func (p *PodmanTestIntegration) CleanupPod() { - // Remove all containers - session := p.Podman([]string{"pod", "rm", "-fa"}) - session.Wait(90) - // Nuke tempdir - if err := os.RemoveAll(p.TempDir); err != nil { - fmt.Printf("%q\n", err) - } -} - -// CleanupVolume cleans up the temporary store -func (p *PodmanTestIntegration) CleanupVolume() { - // Remove all containers - session := p.Podman([]string{"volume", "rm", "-fa"}) - session.Wait(90) - // Nuke tempdir - if err := os.RemoveAll(p.TempDir); err != nil { - fmt.Printf("%q\n", err) - } -} - -// PullImages pulls multiple images -func (p *PodmanTestIntegration) PullImages(images []string) error { - for _, i := range images { - p.PullImage(i) - } - return nil -} - -// PullImage pulls a single image -// TODO should the timeout be configurable? -func (p *PodmanTestIntegration) PullImage(image string) error { - session := p.Podman([]string{"pull", image}) - session.Wait(60) - Expect(session.ExitCode()).To(Equal(0)) - return nil -} - -// InspectContainerToJSON takes the session output of an inspect -// container and returns json -func (s *PodmanSessionIntegration) InspectContainerToJSON() []inspect.ContainerData { - var i []inspect.ContainerData - err := json.Unmarshal(s.Out.Contents(), &i) - Expect(err).To(BeNil()) - return i -} - -// InspectPodToJSON takes the sessions output from a pod inspect and returns json -func (s *PodmanSessionIntegration) InspectPodToJSON() libpod.PodInspect { - var i libpod.PodInspect - err := json.Unmarshal(s.Out.Contents(), &i) - Expect(err).To(BeNil()) - return i -} - -// CreatePod creates a pod with no infra container -// it optionally takes a pod name -func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegration, int, string) { - var podmanArgs = []string{"pod", "create", "--infra=false", "--share", ""} - if name != "" { - podmanArgs = append(podmanArgs, "--name", name) - } - session := p.Podman(podmanArgs) - session.WaitWithDefaultTimeout() - return session, session.ExitCode(), session.OutputToString() -} - -// RunTopContainer runs a simple container in the background that -// runs top. If the name passed != "", it will have a name -func (p *PodmanTestIntegration) RunTopContainer(name string) *PodmanSessionIntegration { - var podmanArgs = []string{"run"} - if name != "" { - podmanArgs = append(podmanArgs, "--name", name) - } - podmanArgs = append(podmanArgs, "-d", ALPINE, "top") - return p.Podman(podmanArgs) -} - -func (p *PodmanTestIntegration) RunTopContainerInPod(name, pod string) *PodmanSessionIntegration { - var podmanArgs = []string{"run", "--pod", pod} - if name != "" { - podmanArgs = append(podmanArgs, "--name", name) - } - podmanArgs = append(podmanArgs, "-d", ALPINE, "top") - return p.Podman(podmanArgs) -} - -// RunLsContainer runs a simple container in the background that -// simply runs ls. If the name passed != "", it will have a name -func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionIntegration, int, string) { - var podmanArgs = []string{"run"} - if name != "" { - podmanArgs = append(podmanArgs, "--name", name) - } - podmanArgs = append(podmanArgs, "-d", ALPINE, "ls") - session := p.Podman(podmanArgs) - session.WaitWithDefaultTimeout() - return session, session.ExitCode(), session.OutputToString() -} - -func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) { - var podmanArgs = []string{"run", "--pod", pod} - if name != "" { - podmanArgs = append(podmanArgs, "--name", name) - } - podmanArgs = append(podmanArgs, "-d", ALPINE, "ls") - session := p.Podman(podmanArgs) - session.WaitWithDefaultTimeout() - return session, session.ExitCode(), session.OutputToString() -} - -// BuildImage uses podman build and buildah to build an image -// called imageName based on a string dockerfile -func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) { - dockerfilePath := filepath.Join(p.TempDir, "Dockerfile") - err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755) - Expect(err).To(BeNil()) - session := p.Podman([]string{"build", "--layers=" + layers, "-t", imageName, "--file", dockerfilePath, p.TempDir}) - session.Wait(120) - Expect(session.ExitCode()).To(Equal(0)) -} - func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() { defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf") os.Setenv("REGISTRIES_CONFIG_PATH", defaultFile) @@ -245,3 +80,4 @@ func (p *PodmanTestIntegration) RestoreArtifact(image string) error { restore.Wait(90) return nil } +func (p *PodmanTestIntegration) StopVarlink() {} diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go index e28c31c3a..c47189a0e 100644 --- a/test/e2e/pause_test.go +++ b/test/e2e/pause_test.go @@ -1,5 +1,3 @@ -// +build !remoteclient - package integration import ( @@ -70,7 +68,6 @@ var _ = Describe("Podman pause", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) cid := session.OutputToString() - result := podmanTest.Podman([]string{"pause", cid}) result.WaitWithDefaultTimeout() diff --git a/test/utils/utils.go b/test/utils/utils.go index 6308197b8..1e0391d2e 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -4,6 +4,7 @@ import ( "bufio" "encoding/json" "fmt" + "github.com/containers/libpod/pkg/rootless" "io/ioutil" "os" "os/exec" @@ -40,6 +41,7 @@ type PodmanTest struct { RemoteTest bool RemotePodmanBinary string VarlinkSession *os.Process + VarlinkEndpoint string } // PodmanSession wraps the gexec.session so we can extend it @@ -67,7 +69,11 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string podmanBinary := p.PodmanBinary if p.RemoteTest { podmanBinary = p.RemotePodmanBinary + if !rootless.IsRootless() { + env = append(env, fmt.Sprintf("PODMAN_VARLINK_ADDRESS=%s", p.VarlinkEndpoint)) + } } + if env == nil { fmt.Printf("Running: %s %s\n", podmanBinary, strings.Join(podmanOptions, " ")) } else { |