diff options
-rw-r--r-- | .cirrus.yml | 22 | ||||
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | cmd/podman/cleanup.go | 39 | ||||
-rw-r--r-- | cmd/podman/commands.go | 3 | ||||
-rw-r--r-- | cmd/podman/common.go | 4 | ||||
-rw-r--r-- | cmd/podman/container.go | 2 | ||||
-rw-r--r-- | cmd/podman/containers_prune.go | 56 | ||||
-rw-r--r-- | cmd/podman/shared/create.go | 1 | ||||
-rw-r--r-- | cmd/podman/shared/intermediate.go | 1 | ||||
-rw-r--r-- | cmd/podman/system.go | 1 | ||||
-rw-r--r-- | cmd/podman/system_prune.go | 5 | ||||
-rw-r--r-- | completions/bash/podman | 1 | ||||
-rw-r--r-- | docs/podman-create.1.md | 10 | ||||
-rw-r--r-- | docs/podman-run.1.md | 70 | ||||
-rw-r--r-- | docs/tutorials/podman_tutorial.md | 2 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 90 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 38 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 1 | ||||
-rw-r--r-- | pkg/spec/spec.go | 18 | ||||
-rw-r--r-- | pkg/varlinkapi/attach.go | 14 | ||||
-rw-r--r-- | test/e2e/libpod_suite_test.go | 1 | ||||
-rw-r--r-- | test/e2e/prune_test.go | 3 | ||||
-rw-r--r-- | test/e2e/run_test.go | 14 |
23 files changed, 282 insertions, 124 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 6c9d199db..6ab8beda3 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -138,7 +138,7 @@ gating_task: - '/usr/local/bin/entrypoint.sh podman-remote-windows' on_failure: - master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' # This task runs `make vendor` followed by ./hack/tree_status.sh to check @@ -167,7 +167,7 @@ vendor_task: - 'cd /go/src/github.com/containers/libpod && ./hack/tree_status.sh' on_failure: - master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' build_each_commit_task: @@ -194,7 +194,7 @@ build_each_commit_task: - 'env GOPATH=/var/tmp/go/ make build-all-new-commits GIT_BASE_BRANCH=origin/$CIRRUS_BASE_BRANCH' on_failure: - master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' # Update metadata on VM images referenced by this repository state @@ -254,9 +254,14 @@ testing_task: setup_environment_script: '$SCRIPT_BASE/setup_environment.sh' unit_test_script: '$SCRIPT_BASE/unit_test.sh' integration_test_script: '$SCRIPT_BASE/integration_test.sh' + audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log' + journalctl_b_script: 'journalctl -b' on_failure: - master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + # Job has already failed, don't fail again and miss collecting data + failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"' + failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"' # This task executes tests under unique environments/conditions @@ -284,9 +289,14 @@ special_testing_task: setup_environment_script: '$SCRIPT_BASE/setup_environment.sh' integration_test_script: '$SCRIPT_BASE/integration_test.sh' + audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log' + journalctl_b_script: 'journalctl -b' on_failure: - master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + # Job has already failed, don't fail again and miss collecting data + failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"' + failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"' # Because system tests are stored within the repository, it is sometimes @@ -362,7 +372,7 @@ cache_images_task: # - commit_and_create_upstream_pr.sh on_failure: - master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' + failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh' # Post message to IRC if everything passed @@ -29,7 +29,15 @@ This project tests all builds against each supported version of Fedora, the late 1. Further work on the podman pod command 1. Further improvements on rootless containers -## [Shortcomings of Rootless Podman](https://github.com/containers/libpod/blob/master/rootless.md) +## Rootless +Podman can be easily run as a normal user, without requiring a setuid binary. +When run without root, Podman containers use user namespaces to set root in the container to the user running Podman. +Rootless Podman runs locked-down containers with no privileges that the user running the container does not have. +Some of these restrictions can be lifted (via `--privileged`, for example), but rootless containers will never have more privileges than the user that launched them. +If you run Podman as your user and mount in `/etc/passwd` from the host, you still won't be able to change it, since your user doesn't have permission to do so. + +Almost all normal Podman functionality is available, though there are some [shortcomings](https://github.com/containers/libpod/blob/master/rootless.md). +Any recent Podman release should be able to run rootless without any additional configuration, though your operating system may require some additional configuration detailed in the [install guide](https://github.com/containers/libpod/blob/master/install.md). ## Out of scope diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go index 9434c68ba..4ff744ae5 100644 --- a/cmd/podman/cleanup.go +++ b/cmd/podman/cleanup.go @@ -1,11 +1,8 @@ package main import ( - "fmt" - "os" - "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -49,38 +46,16 @@ func init() { } func cleanupCmd(c *cliconfig.CleanupValues) error { - runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand) + runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) - cleanupContainers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all") - - ctx := getContext() - - for _, ctr := range cleanupContainers { - hadError := false - if c.Remove { - if err := runtime.RemoveContainer(ctx, ctr, false, true); err != nil { - if lastError != nil { - fmt.Fprintln(os.Stderr, lastError) - } - lastError = errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID()) - hadError = true - } - } else { - if err := ctr.Cleanup(ctx); err != nil { - if lastError != nil { - fmt.Fprintln(os.Stderr, lastError) - } - lastError = errors.Wrapf(err, "failed to cleanup container %v", ctr.ID()) - hadError = true - } - } - if !hadError { - fmt.Println(ctr.ID()) - } + ok, failures, err := runtime.CleanupContainers(getContext(), c) + if err != nil { + return err } - return lastError + + return printCmdResults(ok, failures) } diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index 36c28696f..4b0641d82 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -46,12 +46,10 @@ func getContainerSubCommands() []*cobra.Command { _execCommand, _mountCommand, _portCommand, - _pruneContainersCommand, _refreshCommand, _restoreCommand, _runlabelCommand, _statsCommand, - _stopCommand, _umountCommand, } } @@ -74,7 +72,6 @@ func getTrustSubCommands() []*cobra.Command { // Commands that the local client implements func getSystemSubCommands() []*cobra.Command { return []*cobra.Command{ - _pruneSystemCommand, _renumberCommand, _dfSystemCommand, _migrateCommand, diff --git a/cmd/podman/common.go b/cmd/podman/common.go index eac96d3ba..b02aa5990 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -313,6 +313,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "hostname", "h", "", "Set container hostname", ) + createFlags.Bool( + "http-proxy", true, + "Set proxy environment variables in container based on the host proxy vars", + ) createFlags.String( "image-volume", cliconfig.DefaultImageVolume, "Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore'", diff --git a/cmd/podman/container.go b/cmd/podman/container.go index 52152d50e..b3058bf12 100644 --- a/cmd/podman/container.go +++ b/cmd/podman/container.go @@ -61,9 +61,11 @@ var ( _logsCommand, _pauseCommand, _restartCommand, + _pruneContainersCommand, _runCommand, _rmCommand, _startCommand, + _stopCommand, _topCommand, _unpauseCommand, _waitCommand, diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go index 8270669c9..b052bda36 100644 --- a/cmd/podman/containers_prune.go +++ b/cmd/podman/containers_prune.go @@ -1,14 +1,11 @@ package main import ( - "context" - "github.com/containers/libpod/cmd/podman/cliconfig" "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,39 +38,6 @@ func init() { flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false") } -func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWorkers int, force, volumes bool) error { - var deleteFuncs []shared.ParallelWorkerInput - - filter := func(c *libpod.Container) bool { - state, err := c.State() - if state == libpod.ContainerStateStopped || (state == libpod.ContainerStateExited && err == nil && c.PodID() == "") { - return true - } - return false - } - delContainers, err := runtime.GetContainers(filter) - if err != nil { - return err - } - if len(delContainers) < 1 { - return nil - } - for _, container := range delContainers { - con := container - f := func() error { - return runtime.RemoveContainer(ctx, con, force, volumes) - } - - deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{ - ContainerID: con.ID(), - ParallelFunc: f, - }) - } - // Run the parallel funcs - deleteErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, deleteFuncs) - return printParallelOutput(deleteErrors, errCount) -} - func pruneContainersCmd(c *cliconfig.PruneContainersValues) error { runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) if err != nil { @@ -81,11 +45,23 @@ func pruneContainersCmd(c *cliconfig.PruneContainersValues) error { } defer runtime.Shutdown(false) - maxWorkers := shared.Parallelize("rm") + maxWorkers := shared.DefaultPoolSize("prune") if c.GlobalIsSet("max-workers") { maxWorkers = c.GlobalFlags.MaxWorks } - logrus.Debugf("Setting maximum workers to %d", maxWorkers) - - return pruneContainers(runtime, getContext(), maxWorkers, c.Bool("force"), c.Bool("volumes")) + ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force) + if err != nil { + if errors.Cause(err) == libpod.ErrNoSuchCtr { + if len(c.InputArgs) > 1 { + exitCode = 125 + } else { + exitCode = 1 + } + } + return err + } + if len(failures) > 0 { + exitCode = 125 + } + return printCmdResults(ok, failures) } diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index c521f9cb6..48476e177 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -624,6 +624,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. GroupAdd: c.StringSlice("group-add"), Hostname: c.String("hostname"), HostAdd: c.StringSlice("add-host"), + HTTPProxy: c.Bool("http-proxy"), NoHosts: c.Bool("no-hosts"), IDMappings: idmappings, Image: imageName, diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go index 9c494dec5..a38e4d47a 100644 --- a/cmd/podman/shared/intermediate.go +++ b/cmd/podman/shared/intermediate.go @@ -404,6 +404,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes m["healthcheck-start-period"] = newCRString(c, "healthcheck-start-period") m["healthcheck-timeout"] = newCRString(c, "healthcheck-timeout") m["hostname"] = newCRString(c, "hostname") + m["http-proxy"] = newCRBool(c, "http-proxy") m["image-volume"] = newCRString(c, "image-volume") m["init"] = newCRBool(c, "init") m["init-path"] = newCRString(c, "init-path") diff --git a/cmd/podman/system.go b/cmd/podman/system.go index 528a594de..80080bf44 100644 --- a/cmd/podman/system.go +++ b/cmd/podman/system.go @@ -20,6 +20,7 @@ var ( var systemCommands = []*cobra.Command{ _infoCommand, + _pruneSystemCommand, } func init() { diff --git a/cmd/podman/system_prune.go b/cmd/podman/system_prune.go index 8a648b603..d5b218cd8 100644 --- a/cmd/podman/system_prune.go +++ b/cmd/podman/system_prune.go @@ -81,14 +81,15 @@ Are you sure you want to continue? [y/N] `, volumeString) rmWorkers := shared.Parallelize("rm") ctx := getContext() fmt.Println("Deleted Containers") - lasterr := pruneContainers(runtime, ctx, rmWorkers, false, false) + ok, failures, lasterr := runtime.Prune(ctx, rmWorkers, false) + printCmdResults(ok, failures) fmt.Println("Deleted Pods") pruneValues := cliconfig.PodPruneValues{ PodmanCommand: c.PodmanCommand, Force: c.Force, } - ok, failures, err := runtime.PrunePods(ctx, &pruneValues) + ok, failures, err = runtime.PrunePods(ctx, &pruneValues) if err != nil { if lasterr != nil { logrus.Errorf("%q", lasterr) diff --git a/completions/bash/podman b/completions/bash/podman index 6acdcc05a..b5963f8b9 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1711,6 +1711,7 @@ _podman_container_run() { --gidmap --group-add --hostname -h + --http-proxy --image-volume --init-path --ip diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 52c965293..884a8adcc 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -244,6 +244,16 @@ inside of the container. Read in a line delimited file of environment variables +**--http-proxy**=*true*|*false* + +By default proxy environment variables are passed into the container if set +for the podman process. This can be disabled by setting the `--http-proxy` +option to `false`. The environment variables passed in include `http_proxy`, +`https_proxy`, `ftp_proxy`, `no_proxy`, and also the upper case versions of +those. + +Defaults to `true` + **--expose**=[] Expose a port, or a range of ports (e.g. --expose=3300-3310) to set up port redirection diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index e54e5e691..a0c17652a 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -251,6 +251,16 @@ inside of the container. Read in a line delimited file of environment variables +**--http-proxy**=*true*|*false* + +By default proxy environment variables are passed into the container if set +for the podman process. This can be disabled by setting the `--http-proxy` +option to `false`. The environment variables passed in include `http_proxy`, +`https_proxy`, `ftp_proxy`, `no_proxy`, and also the upper case versions of +those. + +Defaults to `true` + **--expose**=[] Expose a port, or a range of ports (e.g. --expose=3300-3310) to set up port redirection @@ -415,6 +425,36 @@ unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap. Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. +**--mount**=*type=TYPE,TYPE-SPECIFIC-OPTION[,...]* + +Attach a filesystem mount to the container + +Current supported mount TYPES are bind, and tmpfs. + + e.g. + + type=bind,source=/path/on/host,destination=/path/in/container + + type=tmpfs,tmpfs-size=512M,destination=/path/in/container + + Common Options: + + · src, source: mount source spec for bind and volume. Mandatory for bind. + + · dst, destination, target: mount destination spec. + + · ro, read-only: true or false (default). + + Options specific to bind: + + · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2). + + Options specific to tmpfs: + + · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux. + + · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux. + **--name**="" Assign a name to the container @@ -711,36 +751,6 @@ Set the UTS mode for the container **NOTE**: the host mode gives the container access to changing the host's hostname and is therefore considered insecure. -**--mount**=*type=TYPE,TYPE-SPECIFIC-OPTION[,...]* - -Attach a filesystem mount to the container - -Current supported mount TYPES are bind, and tmpfs. - - e.g. - - type=bind,source=/path/on/host,destination=/path/in/container - - type=tmpfs,tmpfs-size=512M,destination=/path/in/container - - Common Options: - - · src, source: mount source spec for bind and volume. Mandatory for bind. - - · dst, destination, target: mount destination spec. - - · ro, read-only: true or false (default). - - Options specific to bind: - - · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2). - - Options specific to tmpfs: - - · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux. - - · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux. - **--userns**="" Set the user namespace mode for the container. The use of userns is disabled by default. diff --git a/docs/tutorials/podman_tutorial.md b/docs/tutorials/podman_tutorial.md index 2abd9c50f..f972853e6 100644 --- a/docs/tutorials/podman_tutorial.md +++ b/docs/tutorials/podman_tutorial.md @@ -99,7 +99,7 @@ sudo cp bin/* /usr/libexec/cni Add a most basic network config ```console mkdir -p /etc/cni/net.d -curl -qsSL https://raw.githubusercontent.com/containers/libpod/master/cni/87-podman-bridge.conflist | tee /etc/cni/net.d/99-loopback.conf +curl -qsSL https://raw.githubusercontent.com/containers/libpod/master/cni/87-podman-bridge.conflist | sudo tee /etc/cni/net.d/99-loopback.conf ``` #### Installing runc ```console diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 9f5fc7e65..9ec897a60 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -786,3 +786,93 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) { } return container.Top(descriptors) } + +// Prune removes stopped containers +func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + err error + ) + + logrus.Debugf("Setting maximum rm workers to %d", maxWorkers) + + filter := func(c *libpod.Container) bool { + state, err := c.State() + if err != nil { + logrus.Error(err) + return false + } + if c.PodID() != "" { + return false + } + if state == libpod.ContainerStateStopped || state == libpod.ContainerStateExited { + return true + } + return false + } + delContainers, err := r.Runtime.GetContainers(filter) + if err != nil { + return ok, failures, err + } + if len(delContainers) < 1 { + return ok, failures, err + } + pool := shared.NewPool("prune", maxWorkers, len(delContainers)) + for _, c := range delContainers { + ctr := c + pool.Add(shared.Job{ + ID: ctr.ID(), + Fn: func() error { + err := r.Runtime.RemoveContainer(ctx, ctr, force, false) + if err != nil { + logrus.Debugf("Failed to prune container %s: %s", ctr.ID(), err.Error()) + } + return err + }, + }) + } + return pool.Run() +} + +// CleanupContainers any leftovers bits of stopped containers +func (r *LocalRuntime) CleanupContainers(ctx context.Context, cli *cliconfig.CleanupValues) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ) + + ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + if err != nil { + return ok, failures, err + } + + for _, ctr := range ctrs { + if cli.Remove { + err = removeContainer(ctx, ctr, r) + } else { + err = cleanupContainer(ctx, ctr, r) + } + + if err == nil { + ok = append(ok, ctr.ID()) + } else { + failures[ctr.ID()] = err + } + } + return ok, failures, nil +} + +func removeContainer(ctx context.Context, ctr *libpod.Container, runtime *LocalRuntime) error { + if err := runtime.RemoveContainer(ctx, ctr, false, true); err != nil { + return errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID()) + } + return nil +} + +func cleanupContainer(ctx context.Context, ctr *libpod.Container, runtime *LocalRuntime) error { + if err := ctr.Cleanup(ctx); err != nil { + return errors.Wrapf(err, "failed to cleanup container %v", ctr.ID()) + } + return nil +} diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index ef6d0efe1..a3a48a564 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -584,7 +584,10 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er } inputStream := os.Stdin if c.NoStdin { - inputStream = nil + inputStream, err = os.Open(os.DevNull) + if err != nil { + return err + } } errChan, err := r.attach(ctx, inputStream, os.Stdout, c.InputArgs[0], false, c.DetachKeys) if err != nil { @@ -852,3 +855,36 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) { } return iopodman.Top().Call(r.Conn, ctr.ID(), descriptors) } + +// Prune removes stopped containers +func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([]string, map[string]error, error) { + + var ( + ok = []string{} + failures = map[string]error{} + ctrs []*Container + err error + ) + logrus.Debugf("Setting maximum rm workers to %d", maxWorkers) + + filters := []string{libpod.ContainerStateExited.String()} + ctrs, err = r.LookupContainersWithStatus(filters) + if err != nil { + return ok, failures, err + } + for _, c := range ctrs { + c := c + _, err := iopodman.RemoveContainer().Call(r.Conn, c.ID(), false, false) + if err != nil { + failures[c.ID()] = err + } else { + ok = append(ok, c.ID()) + } + } + return ok, failures, nil +} + +// Cleanup any leftovers bits of stopped containers +func (r *LocalRuntime) CleanupContainers(ctx context.Context, cli *cliconfig.CleanupValues) ([]string, map[string]error, error) { + return nil, nil, errors.New("container cleanup not supported for remote clients") +} diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index d1b722807..505d87f09 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -86,6 +86,7 @@ type CreateConfig struct { NoHosts bool HostAdd []string //add-host Hostname string //hostname + HTTPProxy bool Image string ImageID string BuiltinImgVolumes map[string]struct{} // volumes defined in the image config diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 4cbed0ea4..383eeadf3 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -192,6 +192,24 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint } g.SetRootReadonly(config.ReadOnlyRootfs) + if config.HTTPProxy { + for _, envSpec := range []string{ + "http_proxy", + "HTTP_PROXY", + "https_proxy", + "HTTPS_PROXY", + "ftp_proxy", + "FTP_PROXY", + "no_proxy", + "NO_PROXY", + } { + envVal := os.Getenv(envSpec) + if envVal != "" { + g.AddProcessEnv(envSpec, envVal) + } + } + } + hostname := config.Hostname if hostname == "" && (config.NetMode.IsHost() || config.UtsMode.IsHost()) { hostname, err = os.Hostname() diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go index 9e2a265be..6c62d3514 100644 --- a/pkg/varlinkapi/attach.go +++ b/pkg/varlinkapi/attach.go @@ -53,7 +53,13 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st if err != nil { return call.ReplyErrorOccurred(err.Error()) } - + state, err := ctr.State() + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + if !start && state != libpod.ContainerStateRunning { + return call.ReplyErrorOccurred("container must be running to attach") + } reader, writer, _, pw, streams := setupStreams(call) go func() { @@ -62,10 +68,10 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st } }() - if start { - finalErr = startAndAttach(ctr, streams, detachKeys, resize, errChan) - } else { + if state == libpod.ContainerStateRunning { finalErr = attach(ctr, streams, detachKeys, resize, errChan) + } else { + finalErr = startAndAttach(ctr, streams, detachKeys, resize, errChan) } if finalErr != libpod.ErrDetach && finalErr != nil { diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 867844c32..10ca9ac47 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -13,7 +13,6 @@ import ( ) func SkipIfRemote() { - ginkgo.Skip("This function is not enabled for remote podman") } func SkipIfRootless() { diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index 544d54b50..377c9f5e1 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -39,7 +39,6 @@ var _ = Describe("Podman prune", func() { }) It("podman container prune containers", func() { - SkipIfRemote() top := podmanTest.RunTopContainer("") top.WaitWithDefaultTimeout() Expect(top.ExitCode()).To(Equal(0)) @@ -102,8 +101,6 @@ var _ = Describe("Podman prune", func() { }) It("podman system prune pods", func() { - SkipIfRemote() - session := podmanTest.Podman([]string{"pod", "create"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index a89ee491b..849fcc477 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -763,4 +763,18 @@ USER mail` session.WaitWithDefaultTimeout() Expect(session.ExitCode()).ToNot(Equal(0)) }) + + It("podman run --http-proxy test", func() { + os.Setenv("http_proxy", "1.2.3.4") + session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "http_proxy"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("1.2.3.4") + Expect(match).Should(BeTrue()) + + session = podmanTest.Podman([]string{"run", "--rm", "--http-proxy=false", ALPINE, "printenv", "http_proxy"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(1)) + os.Unsetenv("http_proxy") + }) }) |