summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md2
-rwxr-xr-xAPI.md5
-rw-r--r--README.md31
-rw-r--r--cmd/podman/build.go27
-rw-r--r--cmd/podman/commands.go5
-rw-r--r--cmd/podman/create.go5
-rw-r--r--cmd/podman/errors.go23
-rw-r--r--cmd/podman/generate.go13
-rw-r--r--cmd/podman/main.go15
-rw-r--r--cmd/podman/play_kube.go2
-rw-r--r--cmd/podman/rm.go20
-rw-r--r--cmd/podman/rmi.go54
-rw-r--r--cmd/podman/varlink/io.podman.varlink9
-rw-r--r--contrib/cirrus/packer/fedora_setup.sh1
-rw-r--r--contrib/cirrus/packer/ubuntu_setup.sh1
-rw-r--r--docs/podman-build.1.md6
-rw-r--r--docs/podman-container-cleanup.1.md2
-rw-r--r--docs/podman-rm.1.md13
-rw-r--r--docs/podman-rmi.1.md10
-rw-r--r--docs/podman-run.1.md14
-rw-r--r--libpod/container_commit.go2
-rw-r--r--libpod/container_internal_linux.go43
-rw-r--r--libpod/options.go4
-rw-r--r--pkg/rootless/rootless_linux.c28
-rw-r--r--pkg/spec/createconfig.go10
-rw-r--r--pkg/spec/spec.go58
-rw-r--r--pkg/varlinkapi/containers.go42
-rw-r--r--pkg/varlinkapi/images.go19
-rw-r--r--pkg/varlinkapi/pods.go20
-rw-r--r--test/e2e/libpod_suite_test.go4
-rw-r--r--test/e2e/rm_test.go5
-rw-r--r--test/e2e/rmi_test.go2
-rw-r--r--test/e2e/rootless_test.go45
-rw-r--r--test/e2e/run_networking_test.go39
-rw-r--r--test/utils/podmantest_test.go2
-rw-r--r--test/utils/utils.go12
-rw-r--r--vendor.conf4
-rw-r--r--vendor/github.com/containers/buildah/buildah.go7
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/build.go19
-rw-r--r--vendor/github.com/containers/buildah/new.go68
-rw-r--r--vendor/github.com/containers/buildah/pkg/cli/common.go10
-rw-r--r--vendor/github.com/containers/buildah/pkg/parse/parse.go6
-rw-r--r--vendor/github.com/containers/buildah/pull.go117
-rw-r--r--vendor/github.com/containers/buildah/unshare/unshare.c140
-rw-r--r--vendor/github.com/containers/buildah/unshare/unshare.go6
-rw-r--r--vendor/github.com/containers/buildah/util/util.go56
-rw-r--r--vendor/github.com/containers/buildah/vendor.conf24
-rw-r--r--vendor/github.com/openshift/imagebuilder/README.md2
-rw-r--r--vendor/github.com/openshift/imagebuilder/builder.go31
-rw-r--r--vendor/github.com/openshift/imagebuilder/dispatchers.go13
50 files changed, 743 insertions, 353 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index a7663f3e3..2946f0b91 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -52,7 +52,7 @@ Briefly describe the problem you are having in a few paragraphs.
(paste your output here)
```
-**Output of `podman info`:**
+**Output of `podman info --debug`:**
```
(paste your output here)
diff --git a/API.md b/API.md
index 685dddf17..c4f23c9bd 100755
--- a/API.md
+++ b/API.md
@@ -229,6 +229,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[error RuntimeError](#RuntimeError)
+[error VolumeNotFound](#VolumeNotFound)
+
## Methods
### <a name="BuildImage"></a>func BuildImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@@ -1741,3 +1743,6 @@ PodNotFound means the pod could not be found by the provided name or ID in local
### <a name="RuntimeError"></a>type RuntimeError
RuntimeErrors generally means a runtime could not be found or gotten.
+### <a name="VolumeNotFound"></a>type VolumeNotFound
+
+VolumeNotFound means the volume could not be found by the name or ID in local storage.
diff --git a/README.md b/README.md
index 52324c860..08c584c72 100644
--- a/README.md
+++ b/README.md
@@ -83,18 +83,23 @@ Information about contributing to this project.
## Buildah and Podman relationship
-Buildah and Podman are two complementary Open-source projects that are available on
-most Linux platforms and both projects reside at [GitHub.com](https://github.com)
-with [Buildah](https://buildah.io) [(GitHub)](https://github.com/containers/buildah) and
-[Podman](https://podman.io) [(GitHub)](https://github.com/containers/libpod). Both Buildah and Podman are
-command line tools that work on OCI images and containers. The two projects
-differentiate in their specialization.
+Buildah and Podman are two complementary open-source projects that are
+available on most Linux platforms and both projects reside at
+[GitHub.com](https://github.com) with Buildah
+[here](https://github.com/containers/buildah) and Podman
+[here](https://github.com/containers/libpod). Both, Buildah and Podman are
+command line tools that work on Open Container Initiative (OCI) images and
+containers. The two projects differentiate in their specialization.
Buildah specializes in building OCI images. Buildah's commands replicate all
-of the commands that are found in a Dockerfile. Buildah’s goal is also to
-provide a lower level coreutils interface to build images, allowing people to build
-containers without requiring a Dockerfile. The intent with Buildah is to allow other
-scripting languages to build container images, without requiring a daemon.
+of the commands that are found in a Dockerfile. This allows building images
+with and without Dockerfiles while not requiring any root privileges.
+Buildah’s ultimate goal is to provide a lower-level coreutils interface to
+build images. The flexibility of building images without Dockerfiles allows
+for the integration of other scripting languages into the build process.
+Buildah follows a simple fork-exec model and does not run as a daemon
+but it is based on a comprehensive API in golang, which can be vendored
+into other tools.
Podman specializes in all of the commands and functions that help you to maintain and modify
OCI images, such as pulling and tagging. It also allows you to create, run, and maintain those containers
@@ -103,12 +108,12 @@ created from those images.
A major difference between Podman and Buildah is their concept of a container. Podman
allows users to create "traditional containers" where the intent of these containers is
to be long lived. While Buildah containers are really just created to allow content
-to be added back to the container image. An easy way to think of it is the
+to be added back to the container image. An easy way to think of it is the
`buildah run` command emulates the RUN command in a Dockerfile while the `podman run`
command emulates the `docker run` command in functionality. Because of this and their underlying
-storage differences, you cannot see Podman containers from within Buildah or vice versa.
+storage differences, you can not see Podman containers from within Buildah or vice versa.
-In short Buildah is an efficient way to create OCI images while Podman allows
+In short, Buildah is an efficient way to create OCI images while Podman allows
you to manage and maintain those images and containers in a production environment using
familiar container cli commands. For more details, see the
[Container Tools Guide](https://github.com/containers/buildah/tree/master/docs/containertools).
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 34fe6a012..e40e35cb5 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -52,12 +52,22 @@ func init() {
flags := buildCommand.Flags()
flags.SetInterspersed(false)
- flags.BoolVar(&layerValues.ForceRm, "force-rm", true, "Always remove intermediate containers after a build, even if the build is unsuccessful. (default true)")
- flags.BoolVar(&layerValues.Layers, "layers", true, "Cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override")
budFlags := buildahcli.GetBudFlags(&budFlagsValues)
+ flag := budFlags.Lookup("pull-always")
+ flag.Value.Set("true")
+ flag.DefValue = "true"
+ layerFlags := buildahcli.GetLayerFlags(&layerValues)
+ flag = layerFlags.Lookup("layers")
+ flag.Value.Set(useLayers())
+ flag.DefValue = (useLayers())
+ flag = layerFlags.Lookup("force-rm")
+ flag.Value.Set("true")
+ flag.DefValue = "true"
+
fromAndBugFlags := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues)
flags.AddFlagSet(&budFlags)
+ flags.AddFlagSet(&layerFlags)
flags.AddFlagSet(&fromAndBugFlags)
}
@@ -179,7 +189,7 @@ func buildCmd(c *cliconfig.BuildValues) error {
}
runtimeFlags := []string{}
- for _, arg := range c.RuntimeOpts {
+ for _, arg := range c.RuntimeFlags {
runtimeFlags = append(runtimeFlags, "--"+arg)
}
// end from buildah
@@ -258,6 +268,7 @@ func buildCmd(c *cliconfig.BuildValues) error {
RuntimeArgs: runtimeFlags,
SignaturePolicyPath: c.SignaturePolicy,
Squash: c.Squash,
+ Target: c.Target,
}
return runtime.Build(getContext(), c, options, dockerfiles)
}
@@ -271,3 +282,13 @@ func Tail(a []string) []string {
}
return []string{}
}
+
+// useLayers returns false if BUILDAH_LAYERS is set to "0" or "false"
+// otherwise it returns true
+func useLayers() string {
+ layers := os.Getenv("BUILDAH_LAYERS")
+ if strings.ToLower(layers) == "false" || layers == "0" {
+ return "false"
+ }
+ return "true"
+}
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index f0d3dbb39..20eb0f490 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -16,8 +16,8 @@ func getMainCommands() []*cobra.Command {
_createCommand,
_diffCommand,
_execCommand,
- generateCommand.Command,
- _containerKubeCommand,
+ _generateCommand,
+ _playCommand,
_psCommand,
_loginCommand,
_logoutCommand,
@@ -38,7 +38,6 @@ func getMainCommands() []*cobra.Command {
_topCommand,
_umountCommand,
_unpauseCommand,
- volumeCommand.Command,
_waitCommand,
}
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 12b793d23..868f90d54 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -646,11 +646,6 @@ func parseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
if util.StringInSlice(".", c.StringSlice("dns-search")) && len(c.StringSlice("dns-search")) > 1 {
return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
}
- if !netMode.IsPrivate() {
- if c.IsSet("dns-search") || c.IsSet("dns") || c.IsSet("dns-opt") {
- return nil, errors.Errorf("specifying DNS flags when network mode is shared with the host or another container is not allowed")
- }
- }
// Validate domains are good
for _, dom := range c.StringSlice("dns-search") {
diff --git a/cmd/podman/errors.go b/cmd/podman/errors.go
new file mode 100644
index 000000000..2572b8779
--- /dev/null
+++ b/cmd/podman/errors.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "syscall"
+
+ "github.com/sirupsen/logrus"
+)
+
+func outputError(err error) {
+ if MainGlobalOpts.LogLevel == "debug" {
+ logrus.Errorf(err.Error())
+ } else {
+ if ee, ok := err.(*exec.ExitError); ok {
+ if status, ok := ee.Sys().(syscall.WaitStatus); ok {
+ exitCode = status.ExitStatus()
+ }
+ }
+ fmt.Fprintln(os.Stderr, "Error:", err.Error())
+ }
+}
diff --git a/cmd/podman/generate.go b/cmd/podman/generate.go
index 66cb7a465..773d625ee 100644
--- a/cmd/podman/generate.go
+++ b/cmd/podman/generate.go
@@ -5,17 +5,18 @@ import (
"github.com/spf13/cobra"
)
-var generateDescription = "Generate structured data based for a containers and pods"
-var generateCommand = cliconfig.PodmanCommand{
-
- Command: &cobra.Command{
+var (
+ generateCommand cliconfig.PodmanCommand
+ generateDescription = "Generate structured data based for a containers and pods"
+ _generateCommand = &cobra.Command{
Use: "generate",
Short: "Generated structured data",
Long: generateDescription,
- },
-}
+ }
+)
func init() {
+ generateCommand.Command = _generateCommand
generateCommand.AddCommand(getGenerateSubCommands()...)
generateCommand.SetUsageTemplate(UsageTemplate())
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index bb21f2f79..19bdb40d6 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -2,11 +2,9 @@ package main
import (
"context"
- "fmt"
"io"
"log/syslog"
"os"
- "os/exec"
"runtime/pprof"
"strings"
"syscall"
@@ -18,7 +16,7 @@ import (
"github.com/containers/libpod/pkg/tracing"
"github.com/containers/libpod/version"
"github.com/containers/storage/pkg/reexec"
- opentracing "github.com/opentracing/opentracing-go"
+ "github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
lsyslog "github.com/sirupsen/logrus/hooks/syslog"
@@ -224,16 +222,7 @@ func main() {
return
}
if err := rootCmd.Execute(); err != nil {
- if MainGlobalOpts.LogLevel == "debug" {
- logrus.Errorf(err.Error())
- } else {
- if ee, ok := err.(*exec.ExitError); ok {
- if status, ok := ee.Sys().(syscall.WaitStatus); ok {
- exitCode = status.ExitStatus()
- }
- }
- fmt.Fprintln(os.Stderr, "Error:", err.Error())
- }
+ outputError(err)
} else {
// The exitCode modified from 125, indicates an application
// running inside of a container failed, as opposed to the
diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go
index 9fc06dde9..a59460b71 100644
--- a/cmd/podman/play_kube.go
+++ b/cmd/podman/play_kube.go
@@ -52,8 +52,6 @@ func init() {
flags.BoolVarP(&playKubeCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.StringVar(&playKubeCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
-
- rootCmd.AddCommand(playKubeCommand.Command)
}
func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index 01ed70f52..2dcb491d7 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -61,15 +62,21 @@ func rmCmd(c *cliconfig.RmValues) error {
}
defer runtime.Shutdown(false)
+ failureCnt := 0
delContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
if err != nil {
if c.Force && len(c.InputArgs) > 0 {
if errors.Cause(err) == libpod.ErrNoSuchCtr {
err = nil
+ } else {
+ failureCnt++
}
runtime.RemoveContainersFromStorage(c.InputArgs)
}
if len(delContainers) == 0 {
+ if err != nil && failureCnt == 0 {
+ exitCode = 1
+ }
return err
}
if err != nil {
@@ -96,5 +103,16 @@ func rmCmd(c *cliconfig.RmValues) error {
// Run the parallel funcs
deleteErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, deleteFuncs)
- return printParallelOutput(deleteErrors, errCount)
+ err = printParallelOutput(deleteErrors, errCount)
+ if err != nil {
+ for _, result := range deleteErrors {
+ if result != nil && errors.Cause(result) != image.ErrNoSuchCtr {
+ failureCnt++
+ }
+ }
+ if failureCnt == 0 {
+ exitCode = 1
+ }
+ }
+ return err
}
diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go
index fbaa19336..709ed14e0 100644
--- a/cmd/podman/rmi.go
+++ b/cmd/podman/rmi.go
@@ -5,6 +5,8 @@ import (
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/storage"
"github.com/pkg/errors"
@@ -29,6 +31,17 @@ var (
}
)
+func imageNotFound(err error) bool {
+ if errors.Cause(err) == image.ErrNoSuchImage {
+ return true
+ }
+ switch err.(type) {
+ case *iopodman.ImageNotFound:
+ return true
+ }
+ return false
+}
+
func init() {
rmiCommand.Command = _rmiCommand
rmiCommand.SetUsageTemplate(UsageTemplate())
@@ -39,10 +52,8 @@ func init() {
func rmiCmd(c *cliconfig.RmiValues) error {
var (
- lastError error
- deleted bool
- deleteErr error
- msg string
+ lastError error
+ failureCnt int
)
ctx := getContext()
@@ -64,19 +75,21 @@ func rmiCmd(c *cliconfig.RmiValues) error {
images := args[:]
removeImage := func(img *adapter.ContainerImage) {
- deleted = true
- msg, deleteErr = runtime.RemoveImage(ctx, img, c.Force)
- if deleteErr != nil {
- if errors.Cause(deleteErr) == storage.ErrImageUsedByContainer {
+ msg, err := runtime.RemoveImage(ctx, img, c.Force)
+ if err != nil {
+ if errors.Cause(err) == storage.ErrImageUsedByContainer {
fmt.Printf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID())
}
+ if !imageNotFound(err) {
+ failureCnt++
+ }
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)
}
- lastError = deleteErr
- } else {
- fmt.Println(msg)
+ lastError = err
+ return
}
+ fmt.Println(msg)
}
if removeAll {
@@ -121,22 +134,21 @@ func rmiCmd(c *cliconfig.RmiValues) error {
for _, i := range images {
newImage, err := runtime.NewImageFromLocal(i)
if err != nil {
- fmt.Fprintln(os.Stderr, err)
+ if lastError != nil {
+ if !imageNotFound(lastError) {
+ failureCnt++
+ }
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = err
continue
}
removeImage(newImage)
}
}
- // If the user calls remove all and there are none, it should not be a
- // non-zero exit
- if !deleted && removeAll {
- return nil
- }
- // the user tries to remove images that do not exist, that should be a
- // non-zero exit
- if !deleted {
- return errors.Errorf("no valid images to delete")
+ if imageNotFound(lastError) && failureCnt == 0 {
+ exitCode = 1
}
return lastError
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index b9e4ea2ef..618af3481 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -1116,16 +1116,19 @@ method GetPodsByContext(all: bool, latest: bool, args: []string) -> (pods: []str
method LoadImage(name: string, inputFile: string, quiet: bool, deleteFile: bool) -> (reply: MoreResponse)
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
-error ImageNotFound (id: string)
+error ImageNotFound (id: string, reason: string)
# ContainerNotFound means the container could not be found by the provided name or ID in local storage.
-error ContainerNotFound (id: string)
+error ContainerNotFound (id: string, reason: string)
# NoContainerRunning means none of the containers requested are running in a command that requires a running container.
error NoContainerRunning ()
# PodNotFound means the pod could not be found by the provided name or ID in local storage.
-error PodNotFound (name: string)
+error PodNotFound (name: string, reason: string)
+
+# VolumeNotFound means the volume could not be found by the name or ID in local storage.
+error VolumeNotFound (id: string, reason: string)
# PodContainerError means a container associated with a pod failed to preform an operation. It contains
# a container ID of the container that failed.
diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh
index 01c468901..de7ad4506 100644
--- a/contrib/cirrus/packer/fedora_setup.sh
+++ b/contrib/cirrus/packer/fedora_setup.sh
@@ -40,6 +40,7 @@ ooe.sh sudo dnf install -y \
golang-github-cpuguy83-go-md2man \
gpgme-devel \
iptables \
+ iproute \
libassuan-devel \
libcap-devel \
libnet \
diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh
index 7d49c5dc7..5b7e1d714 100644
--- a/contrib/cirrus/packer/ubuntu_setup.sh
+++ b/contrib/cirrus/packer/ubuntu_setup.sh
@@ -48,6 +48,7 @@ ooe.sh sudo -E apt-get -qq install \
gettext \
go-md2man \
golang \
+ iproute \
iptables \
libaio-dev \
libapparmor-dev \
diff --git a/docs/podman-build.1.md b/docs/podman-build.1.md
index 76e16b42c..fdae48b93 100644
--- a/docs/podman-build.1.md
+++ b/docs/podman-build.1.md
@@ -362,6 +362,12 @@ Specifies the name which will be assigned to the resulting image if the build
process completes successfully.
If _imageName_ does not include a registry name, the registry name *localhost* will be prepended to the image name.
+**--target** *stageName*
+
+Set the target build stage to build. When building a Dockerfile with multiple build stages, --target
+can be used to specify an intermediate build stage by name as the final stage for the resulting image.
+Commands after the target stage will be skipped.
+
**--tls-verify** *bool-value*
Require HTTPS and verify certificates when talking to container registries (defaults to true).
diff --git a/docs/podman-container-cleanup.1.md b/docs/podman-container-cleanup.1.md
index e375c12ec..2ad39d214 100644
--- a/docs/podman-container-cleanup.1.md
+++ b/docs/podman-container-cleanup.1.md
@@ -30,7 +30,7 @@ The latest option is not supported on the remote client.
`podman container cleanup 860a4b23`
-`podman container-cleanup -a`
+`podman container cleanup -a`
`podman container cleanup --latest`
diff --git a/docs/podman-rm.1.md b/docs/podman-rm.1.md
index 10ebe97f9..dc1729188 100644
--- a/docs/podman-rm.1.md
+++ b/docs/podman-rm.1.md
@@ -1,9 +1,11 @@
-% podman-rm(1)
+% podman-container-rm(1)
## NAME
-podman\-rm - Remove one or more containers
+podman\-container\-rm (podman\-rm) - Remove one or more containers
## SYNOPSIS
+**podman container rm** [*options*] *container*
+
**podman rm** [*options*] *container*
## DESCRIPTION
@@ -57,8 +59,13 @@ Forcibly remove the latest container created.
podman rm -f --latest
```
+## Exit Status
+**_0_** if all specified containers removed
+**_1_** if one of the specified containers did not exist, and no other failures
+**_125_** if command fails for a reason other then an container did not exist
+
## SEE ALSO
-podman(1), podman-rmi(1)
+podman(1), podman-image-rm(1)
## HISTORY
August 2017, Originally compiled by Ryan Cole <rycole@redhat.com>
diff --git a/docs/podman-rmi.1.md b/docs/podman-rmi.1.md
index 9c080c9f1..8c22bba2c 100644
--- a/docs/podman-rmi.1.md
+++ b/docs/podman-rmi.1.md
@@ -1,9 +1,11 @@
-% podman-rmi(1)
+% podman-image-rm(1)
## NAME
-podman\-rmi - Removes one or more images
+podman\-image\-rm (podman\-rmi) - Removes one or more images
## SYNOPSIS
+**podman image rm** *image* ...
+
**podman rmi** *image* ...
## DESCRIPTION
@@ -38,6 +40,10 @@ Remove all images and containers.
```
podman rmi -a -f
```
+## Exit Status
+**_0_** if all specified images removed
+**_1_** if one of the specified images did not exist, and no other failures
+**_125_** if command fails for a reason other then an image did not exist
## SEE ALSO
podman(1)
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index b928f61f5..bbf10a2ce 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -28,6 +28,8 @@ servers in the created `resolv.conf`). Additionally, an empty file is created in
each container to indicate to programs they are running in a container. This file
is located at `/run/.containerenv`.
+When running from a user defined network namespace, the /etc/netns/NSNAME/resolv.conf will be used if it exists, otherwise /etc/resolv.conf will be used.
+
## OPTIONS
**--add-host**=[]
@@ -694,21 +696,21 @@ Current supported mount TYPES are bind, and tmpfs.
Common Options:
- · src, source: mount source spec for bind and volume. Mandatory for bind.
+ · src, source: mount source spec for bind and volume. Mandatory for bind.
- · dst, destination, target: mount destination spec.
+ · dst, destination, target: mount destination spec.
- · ro, read-only: true or false (default).
+ · 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).
+ · 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-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.
+ · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux.
**--userns**=""
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
index 026611e51..5c4fd1a31 100644
--- a/libpod/container_commit.go
+++ b/libpod/container_commit.go
@@ -162,7 +162,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
importBuilder.SetWorkDir(splitChange[1])
}
}
- candidates, _, err := util.ResolveName(destImage, "", sc, c.runtime.store)
+ candidates, _, _, err := util.ResolveName(destImage, "", sc, c.runtime.store)
if err != nil {
return nil, errors.Wrapf(err, "error resolving name %q", destImage)
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 86f94477e..f182b6bdf 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -26,7 +26,6 @@ import (
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/secrets"
"github.com/containers/storage/pkg/idtools"
- "github.com/mrunalp/fileutils"
"github.com/opencontainers/runc/libcontainer/user"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
@@ -677,20 +676,12 @@ func (c *Container) makeBindMounts() error {
// If it doesn't, don't copy them
resolvPath, exists := bindMounts["/etc/resolv.conf"]
if exists {
- resolvDest := filepath.Join(c.state.RunDir, "resolv.conf")
- if err := fileutils.CopyFile(resolvPath, resolvDest); err != nil {
- return errors.Wrapf(err, "error copying resolv.conf from dependency container %s of container %s", depCtr.ID(), c.ID())
- }
- c.state.BindMounts["/etc/resolv.conf"] = resolvDest
- }
+ c.state.BindMounts["/etc/resolv.conf"] = resolvPath
+ }
hostsPath, exists := bindMounts["/etc/hosts"]
if exists {
- hostsDest := filepath.Join(c.state.RunDir, "hosts")
- if err := fileutils.CopyFile(hostsPath, hostsDest); err != nil {
- return errors.Wrapf(err, "error copying hosts file from dependency container %s of container %s", depCtr.ID(), c.ID())
- }
- c.state.BindMounts["/etc/hosts"] = hostsDest
+ c.state.BindMounts["/etc/hosts"] = hostsPath
}
} else {
newResolv, err := c.generateResolvConf()
@@ -705,6 +696,14 @@ func (c *Container) makeBindMounts() error {
}
c.state.BindMounts["/etc/hosts"] = newHosts
}
+
+ if err := label.Relabel(c.state.BindMounts["/etc/hosts"], c.config.MountLabel, true); err != nil {
+ return err
+ }
+
+ if err := label.Relabel(c.state.BindMounts["/etc/resolv.conf"], c.config.MountLabel, true); err != nil {
+ return err
+ }
}
// SHM is always added when we mount the container
@@ -758,8 +757,24 @@ func (c *Container) makeBindMounts() error {
// generateResolvConf generates a containers resolv.conf
func (c *Container) generateResolvConf() (string, error) {
+ resolvConf := "/etc/resolv.conf"
+ for _, ns := range c.config.Spec.Linux.Namespaces {
+ if ns.Type == spec.NetworkNamespace {
+ if ns.Path != "" && !strings.HasPrefix(ns.Path, "/proc/") {
+ definedPath := filepath.Join("/etc/netns", filepath.Base(ns.Path), "resolv.conf")
+ _, err := os.Stat(definedPath)
+ if err == nil {
+ resolvConf = definedPath
+ } else if !os.IsNotExist(err) {
+ return "", errors.Wrapf(err, "failed to stat %s", definedPath)
+ }
+ }
+ break
+ }
+ }
+
// Determine the endpoint for resolv.conf in case it is a symlink
- resolvPath, err := filepath.EvalSymlinks("/etc/resolv.conf")
+ resolvPath, err := filepath.EvalSymlinks(resolvConf)
if err != nil {
return "", err
}
@@ -809,7 +824,7 @@ func (c *Container) generateResolvConf() (string, error) {
}
// Relabel resolv.conf for the container
- if err := label.Relabel(destPath, c.config.MountLabel, false); err != nil {
+ if err := label.Relabel(destPath, c.config.MountLabel, true); err != nil {
return "", err
}
diff --git a/libpod/options.go b/libpod/options.go
index 9aa020b56..e22c81f91 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -904,10 +904,10 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmo
}
ctr.config.PostConfigureNetNS = postConfigureNetNS
- ctr.config.CreateNetNS = true
+ ctr.config.NetMode = namespaces.NetworkMode(netmode)
+ ctr.config.CreateNetNS = !ctr.config.NetMode.IsUserDefined()
ctr.config.PortMappings = portMappings
ctr.config.Networks = networks
- ctr.config.NetMode = namespaces.NetworkMode(netmode)
return nil
}
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index acc5d6b2a..dfbc7fe33 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -109,6 +109,13 @@ reexec_userns_join (int userns, int mountns)
char uid[16];
char **argv;
int pid;
+ char *cwd = getcwd (NULL, 0);
+
+ if (cwd == NULL)
+ {
+ fprintf (stderr, "error getting current working directory: %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
sprintf (uid, "%d", geteuid ());
@@ -154,6 +161,13 @@ reexec_userns_join (int userns, int mountns)
_exit (EXIT_FAILURE);
}
+ if (chdir (cwd) < 0)
+ {
+ fprintf (stderr, "cannot chdir: %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
+ free (cwd);
+
execvp (argv[0], argv);
_exit (EXIT_FAILURE);
@@ -190,6 +204,13 @@ reexec_in_user_namespace (int ready)
char *listen_fds = NULL;
char *listen_pid = NULL;
bool do_socket_activation = false;
+ char *cwd = getcwd (NULL, 0);
+
+ if (cwd == NULL)
+ {
+ fprintf (stderr, "error getting current working directory: %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
listen_pid = getenv("LISTEN_PID");
listen_fds = getenv("LISTEN_FDS");
@@ -265,6 +286,13 @@ reexec_in_user_namespace (int ready)
_exit (EXIT_FAILURE);
}
+ if (chdir (cwd) < 0)
+ {
+ fprintf (stderr, "cannot chdir: %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
+ free (cwd);
+
execvp (argv[0], argv);
_exit (EXIT_FAILURE);
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 8da44a2f0..50e07ee74 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -446,7 +446,15 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l
}
if IsNS(string(c.NetMode)) {
- // pass
+ split := strings.SplitN(string(c.NetMode), ":", 2)
+ if len(split[0]) != 2 {
+ return nil, errors.Errorf("invalid user defined network namespace %q", c.NetMode.UserDefined())
+ }
+ _, err := os.Stat(split[1])
+ if err != nil {
+ return nil, err
+ }
+ options = append(options, libpod.WithNetNS(portBindings, false, string(c.NetMode), networks))
} else if c.NetMode.IsContainer() {
connectedCtr, err := c.Runtime.LookupContainer(c.NetMode.Container())
if err != nil {
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 76b8963ff..28a636fa6 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -3,10 +3,12 @@ package createconfig
import (
"os"
"path"
+ "path/filepath"
"strings"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage/pkg/mount"
+ pmount "github.com/containers/storage/pkg/mount"
"github.com/docker/docker/daemon/caps"
"github.com/docker/go-units"
"github.com/opencontainers/runc/libcontainer/user"
@@ -392,9 +394,65 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint
configSpec.Linux.Resources = &spec.LinuxResources{}
}
+ // Make sure that the bind mounts keep options like nosuid, noexec, nodev.
+ mounts, err := pmount.GetMounts()
+ if err != nil {
+ return nil, err
+ }
+ for i := range configSpec.Mounts {
+ m := &configSpec.Mounts[i]
+ isBind := false
+ for _, o := range m.Options {
+ if o == "bind" || o == "rbind" {
+ isBind = true
+ break
+ }
+ }
+ if !isBind {
+ continue
+ }
+ mount, err := findMount(m.Source, mounts)
+ if err != nil {
+ return nil, err
+ }
+ if mount == nil {
+ continue
+ }
+ next_option:
+ for _, o := range strings.Split(mount.Opts, ",") {
+ if o == "nosuid" || o == "noexec" || o == "nodev" {
+ for _, e := range m.Options {
+ if e == o {
+ continue next_option
+ }
+ }
+ m.Options = append(m.Options, o)
+ }
+ }
+ }
+
return configSpec, nil
}
+func findMount(target string, mounts []*pmount.Info) (*pmount.Info, error) {
+ var err error
+ target, err = filepath.Abs(target)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot resolve %s", target)
+ }
+ var bestSoFar *pmount.Info
+ for _, i := range mounts {
+ if bestSoFar != nil && len(bestSoFar.Mountpoint) > len(i.Mountpoint) {
+ // Won't be better than what we have already found
+ continue
+ }
+ if strings.HasPrefix(target, i.Mountpoint) {
+ bestSoFar = i
+ }
+ }
+ return bestSoFar, nil
+}
+
func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) {
if config.PidMode.IsHost() && rootless.IsRootless() {
return
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index 7345a1dd8..ad9f107a7 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -47,7 +47,7 @@ func (i *LibpodAPI) ListContainers(call iopodman.VarlinkCall) error {
func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
ctr, err := i.Runtime.LookupContainer(id)
if err != nil {
- return call.ReplyContainerNotFound(id)
+ return call.ReplyContainerNotFound(id, err.Error())
}
opts := shared.PsOptions{
Namespace: true,
@@ -64,7 +64,7 @@ func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
inspectInfo, err := ctr.Inspect(true)
if err != nil {
@@ -90,7 +90,7 @@ func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) err
func (i *LibpodAPI) ListContainerProcesses(call iopodman.VarlinkCall, name string, opts []string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
containerState, err := ctr.State()
if err != nil {
@@ -118,7 +118,7 @@ func (i *LibpodAPI) GetContainerLogs(call iopodman.VarlinkCall, name string) err
var logs []string
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
logPath := ctr.LogPath()
@@ -198,7 +198,7 @@ func (i *LibpodAPI) ListContainerChanges(call iopodman.VarlinkCall, name string)
func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
outputFile, err := ioutil.TempFile("", "varlink_recv")
if err != nil {
@@ -220,7 +220,7 @@ func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath str
func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
containerStats, err := ctr.GetContainerStats(&libpod.ContainerStats{})
if err != nil {
@@ -251,7 +251,7 @@ func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) er
func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
state, err := ctr.State()
if err != nil {
@@ -270,7 +270,7 @@ func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error
func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
if err := ctr.StopWithTimeout(uint(timeout)); err != nil && err != libpod.ErrCtrStopped {
return call.ReplyErrorOccurred(err.Error())
@@ -282,7 +282,7 @@ func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeou
func (i *LibpodAPI) RestartContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
if err := ctr.RestartWithTimeout(getContext(), uint(timeout)); err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -311,7 +311,7 @@ func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal
}
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
if err := ctr.Kill(killSignal); err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -323,7 +323,7 @@ func (i *LibpodAPI) KillContainer(call iopodman.VarlinkCall, name string, signal
func (i *LibpodAPI) PauseContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
if err := ctr.Pause(); err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -335,7 +335,7 @@ func (i *LibpodAPI) PauseContainer(call iopodman.VarlinkCall, name string) error
func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
if err := ctr.Unpause(); err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -347,7 +347,7 @@ func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) err
func (i *LibpodAPI) WaitContainer(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
exitCode, err := ctr.Wait()
if err != nil {
@@ -362,7 +362,7 @@ func (i *LibpodAPI) RemoveContainer(call iopodman.VarlinkCall, name string, forc
ctx := getContext()
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
if err := i.Runtime.RemoveContainer(ctx, ctr, force, removeVolumes); err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -398,7 +398,7 @@ func (i *LibpodAPI) DeleteStoppedContainers(call iopodman.VarlinkCall) error {
func (i *LibpodAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
status, err := ctr.State()
@@ -427,7 +427,7 @@ func (i *LibpodAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string,
ctx := getContext()
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
options := libpod.ContainerCheckpointOptions{
@@ -446,7 +446,7 @@ func (i *LibpodAPI) ContainerRestore(call iopodman.VarlinkCall, name string, kee
ctx := getContext()
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
options := libpod.ContainerCheckpointOptions{
@@ -475,7 +475,7 @@ func getArtifact(ctr *libpod.Container) (*cc.CreateConfig, error) {
func (i *LibpodAPI) ContainerConfig(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyErrorOccurred(err.Error())
+ return call.ReplyContainerNotFound(name, err.Error())
}
config := ctr.Config()
b, err := json.Marshal(config)
@@ -489,7 +489,7 @@ func (i *LibpodAPI) ContainerConfig(call iopodman.VarlinkCall, name string) erro
func (i *LibpodAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifactName string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyErrorOccurred(err.Error())
+ return call.ReplyContainerNotFound(name, err.Error())
}
artifacts, err := ctr.GetArtifact(artifactName)
if err != nil {
@@ -506,7 +506,7 @@ func (i *LibpodAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifact
func (i *LibpodAPI) ContainerInspectData(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyErrorOccurred(err.Error())
+ return call.ReplyContainerNotFound(name, err.Error())
}
data, err := ctr.Inspect(true)
if err != nil {
@@ -524,7 +524,7 @@ func (i *LibpodAPI) ContainerInspectData(call iopodman.VarlinkCall, name string)
func (i *LibpodAPI) ContainerStateData(call iopodman.VarlinkCall, name string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyErrorOccurred(err.Error())
+ return call.ReplyContainerNotFound(name, err.Error())
}
data, err := ctr.ContainerState()
if err != nil {
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index a27bdb9e5..210f139ce 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -73,7 +73,7 @@ func (i *LibpodAPI) ListImages(call iopodman.VarlinkCall) error {
func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, id string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(id)
if err != nil {
- return call.ReplyImageNotFound(id)
+ return call.ReplyImageNotFound(id, err.Error())
}
labels, err := newImage.Labels(getContext())
if err != nil {
@@ -266,7 +266,7 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI
func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
- return call.ReplyImageNotFound(name)
+ return call.ReplyImageNotFound(name, err.Error())
}
inspectInfo, err := newImage.Inspect(getContext())
if err != nil {
@@ -284,7 +284,7 @@ func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error {
func (i *LibpodAPI) HistoryImage(call iopodman.VarlinkCall, name string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
- return call.ReplyImageNotFound(name)
+ return call.ReplyImageNotFound(name, err.Error())
}
history, err := newImage.History(getContext())
if err != nil {
@@ -313,7 +313,7 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVe
)
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
- return call.ReplyImageNotFound(err.Error())
+ return call.ReplyImageNotFound(name, err.Error())
}
destname := name
if tag != "" {
@@ -409,7 +409,7 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, tlsVe
func (i *LibpodAPI) TagImage(call iopodman.VarlinkCall, name, tag string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
- return call.ReplyImageNotFound(name)
+ return call.ReplyImageNotFound(name, err.Error())
}
if err := newImage.TagImage(tag); err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -423,7 +423,7 @@ func (i *LibpodAPI) RemoveImage(call iopodman.VarlinkCall, name string, force bo
ctx := getContext()
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
- return call.ReplyImageNotFound(name)
+ return call.ReplyImageNotFound(name, err.Error())
}
_, err = i.Runtime.RemoveImage(ctx, newImage, force)
if err != nil {
@@ -512,7 +512,7 @@ func (i *LibpodAPI) DeleteUnusedImages(call iopodman.VarlinkCall) error {
func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, changes []string, author, message string, pause bool, manifestType string) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
- return call.ReplyContainerNotFound(name)
+ return call.ReplyContainerNotFound(name, err.Error())
}
sc := image.GetSystemContext(i.Runtime.GetConfig().SignaturePolicyPath, "", false)
var mimeType string
@@ -576,7 +576,7 @@ func (i *LibpodAPI) ImportImage(call iopodman.VarlinkCall, source, reference, me
func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination string, compress bool, tags []string) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
- return call.ReplyImageNotFound(name)
+ return call.ReplyImageNotFound(name, err.Error())
}
additionalTags, err := image.GetAdditionalTags(tags)
@@ -741,6 +741,9 @@ func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall, all bool) error {
func (i *LibpodAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageSaveOptions) error {
newImage, err := i.Runtime.ImageRuntime().NewFromLocal(options.Name)
if err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchImage {
+ return call.ReplyImageNotFound(options.Name, err.Error())
+ }
return call.ReplyErrorOccurred(err.Error())
}
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index 738a10b2a..4ca4c4270 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -86,7 +86,7 @@ func (i *LibpodAPI) ListPods(call iopodman.VarlinkCall) error {
func (i *LibpodAPI) GetPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
opts := shared.PsOptions{}
@@ -102,7 +102,7 @@ func (i *LibpodAPI) GetPod(call iopodman.VarlinkCall, name string) error {
func (i *LibpodAPI) InspectPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
inspectData, err := pod.Inspect()
if err != nil {
@@ -119,7 +119,7 @@ func (i *LibpodAPI) InspectPod(call iopodman.VarlinkCall, name string) error {
func (i *LibpodAPI) StartPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
ctnrs, err := pod.AllContainers()
if err != nil {
@@ -140,7 +140,7 @@ func (i *LibpodAPI) StartPod(call iopodman.VarlinkCall, name string) error {
func (i *LibpodAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int64) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
ctrErrs, err := pod.StopWithTimeout(getContext(), true, int(timeout))
callErr := handlePodCall(call, pod, ctrErrs, err)
@@ -154,7 +154,7 @@ func (i *LibpodAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int6
func (i *LibpodAPI) RestartPod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
ctnrs, err := pod.AllContainers()
if err != nil {
@@ -181,7 +181,7 @@ func (i *LibpodAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
ctrErrs, err := pod.Kill(killSignal)
callErr := handlePodCall(call, pod, ctrErrs, err)
@@ -195,7 +195,7 @@ func (i *LibpodAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64
func (i *LibpodAPI) PausePod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
ctrErrs, err := pod.Pause()
callErr := handlePodCall(call, pod, ctrErrs, err)
@@ -209,7 +209,7 @@ func (i *LibpodAPI) PausePod(call iopodman.VarlinkCall, name string) error {
func (i *LibpodAPI) UnpausePod(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
ctrErrs, err := pod.Unpause()
callErr := handlePodCall(call, pod, ctrErrs, err)
@@ -224,7 +224,7 @@ func (i *LibpodAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool
ctx := getContext()
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
if err = i.Runtime.RemovePod(ctx, pod, force, force); err != nil {
return call.ReplyErrorOccurred(err.Error())
@@ -237,7 +237,7 @@ func (i *LibpodAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool
func (i *LibpodAPI) GetPodStats(call iopodman.VarlinkCall, name string) error {
pod, err := i.Runtime.LookupPod(name)
if err != nil {
- return call.ReplyPodNotFound(name)
+ return call.ReplyPodNotFound(name, err.Error())
}
prevStats := make(map[string]*libpod.ContainerStats)
podStats, err := pod.GetPodStats(prevStats)
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 4b4baa93c..33e05b872 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -28,8 +28,8 @@ func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration
}
// PodmanAsUser is the exec call to podman on the filesystem with the specified uid/gid and environment
-func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, env []string) *PodmanSessionIntegration {
- podmanSession := p.PodmanAsUserBase(args, uid, gid, env)
+func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd string, env []string) *PodmanSessionIntegration {
+ podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env)
return &PodmanSessionIntegration{podmanSession}
}
diff --git a/test/e2e/rm_test.go b/test/e2e/rm_test.go
index bc1431bce..71dacfa80 100644
--- a/test/e2e/rm_test.go
+++ b/test/e2e/rm_test.go
@@ -128,4 +128,9 @@ var _ = Describe("Podman rm", func() {
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
})
+ It("podman rm bogus container", func() {
+ session := podmanTest.Podman([]string{"rm", "bogus"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(1))
+ })
})
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index c160e1bc5..dcbda2df4 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -36,7 +36,7 @@ var _ = Describe("Podman rmi", func() {
It("podman rmi bogus image", func() {
session := podmanTest.Podman([]string{"rmi", "debian:6.0.10"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Equal(125))
+ Expect(session.ExitCode()).To(Equal(1))
})
diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go
index 2b84d34c9..aa8ed6faa 100644
--- a/test/e2e/rootless_test.go
+++ b/test/e2e/rootless_test.go
@@ -60,7 +60,7 @@ var _ = Describe("Podman rootless", func() {
for _, v := range commands {
env := os.Environ()
env = append(env, "USER=foo")
- cmd := podmanTest.PodmanAsUser([]string{v}, 1000, 1000, env)
+ cmd := podmanTest.PodmanAsUser([]string{v}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
}
@@ -128,13 +128,13 @@ var _ = Describe("Podman rootless", func() {
env = append(env, "PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS=1")
env = append(env, "USER=foo")
- cmd := rootlessTest.PodmanAsUser([]string{"pod", "create", "--infra=false"}, 1000, 1000, env)
+ cmd := rootlessTest.PodmanAsUser([]string{"pod", "create", "--infra=false"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
podId := cmd.OutputToString()
args := []string{"run", "--pod", podId, "--rootfs", mountPath, "echo", "hello"}
- cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
Expect(cmd.LineInOutputContains("hello")).To(BeTrue())
@@ -158,7 +158,7 @@ var _ = Describe("Podman rootless", func() {
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
env = append(env, fmt.Sprintf("HOME=%s", home))
env = append(env, "USER=foo")
- cmd := podmanTest.PodmanAsUser([]string{"search", "docker.io/busybox"}, 1000, 1000, env)
+ cmd := podmanTest.PodmanAsUser([]string{"search", "docker.io/busybox"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
})
@@ -175,65 +175,65 @@ var _ = Describe("Podman rootless", func() {
allArgs := append([]string{"run"}, args...)
allArgs = append(allArgs, "--rootfs", mountPath, "echo", "hello")
- cmd := rootlessTest.PodmanAsUser(allArgs, 1000, 1000, env)
+ cmd := rootlessTest.PodmanAsUser(allArgs, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
Expect(cmd.LineInOutputContains("hello")).To(BeTrue())
- cmd = rootlessTest.PodmanAsUser([]string{"rm", "-l", "-f"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"rm", "-l", "-f"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
allArgs = append([]string{"run", "-d"}, args...)
allArgs = append(allArgs, "--security-opt", "seccomp=unconfined", "--rootfs", mountPath, "top")
- cmd = rootlessTest.PodmanAsUser(allArgs, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser(allArgs, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
- cmd = rootlessTest.PodmanAsUser([]string{"restart", "-l", "-t", "0"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"restart", "-l", "-t", "0"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
canUseExec := canExec()
if canUseExec {
- cmd = rootlessTest.PodmanAsUser([]string{"top", "-l"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"top", "-l"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
}
- cmd = rootlessTest.PodmanAsUser([]string{"rm", "-l", "-f"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"rm", "-l", "-f"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
allArgs = append([]string{"run", "-d"}, args...)
allArgs = append(allArgs, "--security-opt", "seccomp=unconfined", "--rootfs", mountPath, "unshare", "-r", "unshare", "-r", "top")
- cmd = rootlessTest.PodmanAsUser(allArgs, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser(allArgs, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
- cmd = rootlessTest.PodmanAsUser([]string{"stop", "-l", "-t", "0"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"stop", "-l", "-t", "0"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
- cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l", "--type", "container", "--format", "{{ .State.Status }}"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l", "--type", "container", "--format", "{{ .State.Status }}"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.LineInOutputContains("exited")).To(BeTrue())
- cmd = rootlessTest.PodmanAsUser([]string{"start", "-l"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"start", "-l"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
- cmd = rootlessTest.PodmanAsUser([]string{"stop", "-l", "-t", "0"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"stop", "-l", "-t", "0"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
- cmd = rootlessTest.PodmanAsUser([]string{"start", "-l"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"start", "-l"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
if len(args) == 0 {
- cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
data := cmd.InspectContainerToJSON()
@@ -244,24 +244,23 @@ var _ = Describe("Podman rootless", func() {
Skip("ioctl(NS_GET_PARENT) not supported.")
}
- cmd = rootlessTest.PodmanAsUser([]string{"exec", "-l", "echo", "hello"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"exec", "-l", "echo", "hello"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
Expect(cmd.LineInOutputContains("hello")).To(BeTrue())
- cmd = rootlessTest.PodmanAsUser([]string{"ps", "-l", "-q"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"ps", "-l", "-q"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
cid := cmd.OutputToString()
- cmd = rootlessTest.PodmanAsUser([]string{"exec", "-l", "sh", "-c", "echo SeCreTMessage > /file"}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"exec", "-l", "sh", "-c", "echo SeCreTMessage > /file"}, 1000, 1000, "", env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
- path := filepath.Join(home, "export.tar")
- cmd = rootlessTest.PodmanAsUser([]string{"export", "-o", path, cid}, 1000, 1000, env)
+ cmd = rootlessTest.PodmanAsUser([]string{"export", "-o", "export.tar", cid}, 1000, 1000, home, env)
cmd.WaitWithDefaultTimeout()
- content, err := ioutil.ReadFile(path)
+ content, err := ioutil.ReadFile(filepath.Join(home, "export.tar"))
Expect(err).To(BeNil())
Expect(strings.Contains(string(content), "SeCreTMessage")).To(BeTrue())
}
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 1c09a4d0b..a07e4d047 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -36,19 +36,19 @@ var _ = Describe("Podman run networking", func() {
})
It("podman run network connection with default bridge", func() {
- session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "wget", "www.projectatomic.io"})
+ session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
Expect(session.ExitCode()).To(Equal(0))
})
It("podman run network connection with host", func() {
- session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.projectatomic.io"})
+ session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
Expect(session.ExitCode()).To(Equal(0))
})
It("podman run network connection with loopback", func() {
- session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.projectatomic.io"})
+ session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
Expect(session.ExitCode()).To(Equal(0))
})
@@ -178,4 +178,37 @@ var _ = Describe("Podman run networking", func() {
Expect(exec4.ExitCode()).To(Equal(0))
Expect(exec4.OutputToString()).To(ContainSubstring("192.0.2.2 test1"))
})
+
+ It("podman run network in user created network namespace", func() {
+ if Containerized() {
+ Skip("Can not be run within a container.")
+ }
+ SystemExec("ip", []string{"netns", "add", "xxx"})
+ session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxx", ALPINE, "wget", "www.podman.io"})
+ session.Wait(90)
+ Expect(session.ExitCode()).To(Equal(0))
+ SystemExec("ip", []string{"netns", "delete", "xxx"})
+ })
+
+ It("podman run n user created network namespace with resolv.conf", func() {
+ if Containerized() {
+ Skip("Can not be run within a container.")
+ }
+ SystemExec("ip", []string{"netns", "add", "xxx"})
+ SystemExec("mkdir", []string{"-p", "/etc/netns/xxx"})
+ SystemExec("bash", []string{"-c", "echo nameserver 11.11.11.11 > /etc/netns/xxx/resolv.conf"})
+ session := podmanTest.Podman([]string{"run", "--net", "ns:/run/netns/xxx", ALPINE, "cat", "/etc/resolv.conf"})
+ session.Wait(90)
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("11.11.11.11"))
+ SystemExec("ip", []string{"netns", "delete", "xxx"})
+ SystemExec("rm", []string{"-rf", "/etc/netns/xxx"})
+ })
+
+ It("podman run network in bogus user created network namespace", func() {
+ session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxy", ALPINE, "wget", "www.podman.io"})
+ session.Wait(90)
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session.ErrorToString()).To(ContainSubstring("stat /run/netns/xxy: no such file or directory"))
+ })
})
diff --git a/test/utils/podmantest_test.go b/test/utils/podmantest_test.go
index 60e3e2a97..28f294a94 100644
--- a/test/utils/podmantest_test.go
+++ b/test/utils/podmantest_test.go
@@ -23,7 +23,7 @@ var _ = Describe("PodmanTest test", func() {
FakeOutputs["check"] = []string{"check"}
os.Setenv("HOOK_OPTION", "hook_option")
env := os.Environ()
- session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, env)
+ session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, "", env)
os.Unsetenv("HOOK_OPTION")
session.WaitWithDefaultTimeout()
Expect(session.Command.Process).ShouldNot(BeNil())
diff --git a/test/utils/utils.go b/test/utils/utils.go
index aace018cd..098779321 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -61,7 +61,7 @@ func (p *PodmanTest) MakeOptions(args []string) []string {
// PodmanAsUserBase exec podman as user. uid and gid is set for credentials useage. env is used
// to record the env for debugging
-func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, env []string) *PodmanSession {
+func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string) *PodmanSession {
var command *exec.Cmd
podmanOptions := p.MakeOptions(args)
podmanBinary := p.PodmanBinary
@@ -74,14 +74,18 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, env []stri
fmt.Printf("Running: (env: %v) %s %s\n", env, podmanBinary, strings.Join(podmanOptions, " "))
}
if uid != 0 || gid != 0 {
- nsEnterOpts := append([]string{"--userspec", fmt.Sprintf("%d:%d", uid, gid), "/", podmanBinary}, podmanOptions...)
- command = exec.Command("chroot", nsEnterOpts...)
+ pythonCmd := fmt.Sprintf("import os; import sys; uid = %d; gid = %d; cwd = '%s'; os.setgid(gid); os.setuid(uid); os.chdir(cwd) if len(cwd)>0 else True; os.execv(sys.argv[1], sys.argv[1:])", gid, uid, cwd)
+ nsEnterOpts := append([]string{"-c", pythonCmd, podmanBinary}, podmanOptions...)
+ command = exec.Command("python", nsEnterOpts...)
} else {
command = exec.Command(podmanBinary, podmanOptions...)
}
if env != nil {
command.Env = env
}
+ if cwd != "" {
+ command.Dir = cwd
+ }
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
if err != nil {
@@ -92,7 +96,7 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, env []stri
// PodmanBase exec podman with default env.
func (p *PodmanTest) PodmanBase(args []string) *PodmanSession {
- return p.PodmanAsUserBase(args, 0, 0, nil)
+ return p.PodmanAsUserBase(args, 0, 0, "", nil)
}
// WaitForContainer waits on a started container
diff --git a/vendor.conf b/vendor.conf
index ff1a9c4d5..445f0844a 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -93,13 +93,13 @@ k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apim
k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
github.com/varlink/go 3ac79db6fd6aec70924193b090962f92985fe199
-github.com/containers/buildah 973bb88ef1861a5b782c722c471dd79b6732852c
+github.com/containers/buildah v1.7
# TODO: Gotty has not been updated since 2012. Can we find replacement?
github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512
# do not go beyond the below commit as the next one requires a more recent
# docker which is in conflict with openshift/imagebuilder
github.com/fsouza/go-dockerclient 29c1814d12c072344bb91aac5d2ff719db39c523
-github.com/openshift/imagebuilder 474d0f9df2cbabf006bd2b1c263a7b0789e228e0
+github.com/openshift/imagebuilder 36823496a6868f72bc36282cc475eb8a070c0934
github.com/ulikunitz/xz v0.5.5
github.com/coreos/go-iptables v0.4.0
github.com/google/shlex c34317bd91bf98fab745d77b03933cf8769299fe
diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go
index 8b9baea12..755bc348e 100644
--- a/vendor/github.com/containers/buildah/buildah.go
+++ b/vendor/github.com/containers/buildah/buildah.go
@@ -26,7 +26,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
- Version = "1.7-dev"
+ Version = "1.7"
// The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to
@@ -336,11 +336,6 @@ type BuilderOptions struct {
// needs to be pulled and the image name alone can not be resolved to a
// reference to a source image. No separator is implicitly added.
Registry string
- // Transport is a value which is prepended to the image's name, if it
- // needs to be pulled and the image name alone, or the image name and
- // the registry together, can not be resolved to a reference to a
- // source image. No separator is implicitly added.
- Transport string
// PullBlobDirectory is the name of a directory in which we'll attempt
// to store copies of layer blobs that we pull down, if any. It should
// already exist.
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go
index 56ab7aa57..d69eab52f 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/build.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/build.go
@@ -62,11 +62,6 @@ type BuildOptions struct {
// needs to be pulled and the image name alone can not be resolved to a
// reference to a source image. No separator is implicitly added.
Registry string
- // Transport is a value which is prepended to the image's name, if it
- // needs to be pulled and the image name alone, or the image name and
- // the registry together, can not be resolved to a reference to a
- // source image. No separator is implicitly added.
- Transport string
// IgnoreUnrecognizedInstructions tells us to just log instructions we
// don't recognize, and try to keep going.
IgnoreUnrecognizedInstructions bool
@@ -171,6 +166,8 @@ type BuildOptions struct {
ForceRmIntermediateCtrs bool
// BlobDirectory is a directory which we'll use for caching layer blobs.
BlobDirectory string
+ // Target the targeted FROM in the Dockerfile to build
+ Target string
}
// Executor is a buildah-based implementation of the imagebuilder.Executor
@@ -184,7 +181,6 @@ type Executor struct {
builder *buildah.Builder
pullPolicy buildah.PullPolicy
registry string
- transport string
ignoreUnrecognizedInstructions bool
quiet bool
runtime string
@@ -580,7 +576,6 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) {
contextDir: options.ContextDirectory,
pullPolicy: options.PullPolicy,
registry: options.Registry,
- transport: options.Transport,
ignoreUnrecognizedInstructions: options.IgnoreUnrecognizedInstructions,
quiet: options.Quiet,
runtime: options.Runtime,
@@ -670,7 +665,6 @@ func (b *Executor) Prepare(ctx context.Context, stage imagebuilder.Stage, from s
FromImage: from,
PullPolicy: b.pullPolicy,
Registry: b.registry,
- Transport: b.transport,
PullBlobDirectory: b.blobDirectory,
SignaturePolicyPath: b.signaturePolicyPath,
ReportWriter: b.reportWriter,
@@ -783,7 +777,7 @@ func (b *Executor) resolveNameToImageRef() (types.ImageReference, error) {
if b.output != "" {
imageRef, err = alltransports.ParseImageName(b.output)
if err != nil {
- candidates, _, err := util.ResolveName(b.output, "", b.systemContext, b.store)
+ candidates, _, _, err := util.ResolveName(b.output, "", b.systemContext, b.store)
if err != nil {
return nil, errors.Wrapf(err, "error parsing target image name %q", b.output)
}
@@ -1441,6 +1435,13 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
if err != nil {
return "", nil, errors.Wrap(err, "error reading multiple stages")
}
+ if options.Target != "" {
+ stagesTargeted, ok := stages.ThroughTarget(options.Target)
+ if !ok {
+ return "", nil, errors.Errorf("The target %q was not found in the provided Dockerfile", options.Target)
+ }
+ stages = stagesTargeted
+ }
return exec.Build(ctx, stages)
}
diff --git a/vendor/github.com/containers/buildah/new.go b/vendor/github.com/containers/buildah/new.go
index 7e7f97e49..01c2e733f 100644
--- a/vendor/github.com/containers/buildah/new.go
+++ b/vendor/github.com/containers/buildah/new.go
@@ -28,15 +28,14 @@ const (
minimumTruncatedIDLength = 3
)
-func pullAndFindImage(ctx context.Context, store storage.Store, imageName string, options BuilderOptions, sc *types.SystemContext) (*storage.Image, types.ImageReference, error) {
+func pullAndFindImage(ctx context.Context, store storage.Store, transport string, imageName string, options BuilderOptions, sc *types.SystemContext) (*storage.Image, types.ImageReference, error) {
pullOptions := PullOptions{
ReportWriter: options.ReportWriter,
Store: store,
SystemContext: options.SystemContext,
- Transport: options.Transport,
BlobDirectory: options.PullBlobDirectory,
}
- ref, err := pullImage(ctx, store, imageName, pullOptions, sc)
+ ref, err := pullImage(ctx, store, transport, imageName, pullOptions, sc)
if err != nil {
logrus.Debugf("error pulling image %q: %v", imageName, err)
return nil, nil, err
@@ -101,16 +100,16 @@ func newContainerIDMappingOptions(idmapOptions *IDMappingOptions) storage.IDMapp
return options
}
-func resolveImage(ctx context.Context, systemContext *types.SystemContext, store storage.Store, options BuilderOptions) (types.ImageReference, *storage.Image, error) {
+func resolveImage(ctx context.Context, systemContext *types.SystemContext, store storage.Store, options BuilderOptions) (types.ImageReference, string, *storage.Image, error) {
type failure struct {
resolvedImageName string
err error
}
-
- candidates, searchRegistriesWereUsedButEmpty, err := util.ResolveName(options.FromImage, options.Registry, systemContext, store)
+ candidates, transport, searchRegistriesWereUsedButEmpty, err := util.ResolveName(options.FromImage, options.Registry, systemContext, store)
if err != nil {
- return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", options.FromImage)
+ return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", options.FromImage)
}
+
failures := []failure{}
for _, image := range candidates {
var err error
@@ -118,25 +117,25 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
if img, err := store.Image(image); err == nil && img != nil && strings.HasPrefix(img.ID, image) {
ref, err := is.Transport.ParseStoreReference(store, img.ID)
if err != nil {
- return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID)
+ return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID)
}
- return ref, img, nil
+ return ref, transport, img, nil
}
}
if options.PullPolicy == PullAlways {
- pulledImg, pulledReference, err := pullAndFindImage(ctx, store, image, options, systemContext)
+ pulledImg, pulledReference, err := pullAndFindImage(ctx, store, transport, image, options, systemContext)
if err != nil {
logrus.Debugf("unable to pull and read image %q: %v", image, err)
failures = append(failures, failure{resolvedImageName: image, err: err})
continue
}
- return pulledReference, pulledImg, nil
+ return pulledReference, transport, pulledImg, nil
}
srcRef, err := alltransports.ParseImageName(image)
if err != nil {
- if options.Transport == "" {
+ if transport == "" {
logrus.Debugf("error parsing image name %q: %v", image, err)
failures = append(failures, failure{
resolvedImageName: image,
@@ -144,12 +143,13 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
})
continue
}
- logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, options.Transport, err)
- transport := options.Transport
+ logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, transport, err)
+
+ trans := transport
if transport != util.DefaultTransport {
- transport = transport + ":"
+ trans = trans + ":"
}
- srcRef2, err := alltransports.ParseImageName(transport + image)
+ srcRef2, err := alltransports.ParseImageName(trans + image)
if err != nil {
logrus.Debugf("error parsing image name %q: %v", transport+image, err)
failures = append(failures, failure{
@@ -163,19 +163,19 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
destImage, err := localImageNameForReference(ctx, store, srcRef, options.FromImage)
if err != nil {
- return nil, nil, errors.Wrapf(err, "error computing local image name for %q", transports.ImageName(srcRef))
+ return nil, "", nil, errors.Wrapf(err, "error computing local image name for %q", transports.ImageName(srcRef))
}
if destImage == "" {
- return nil, nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef))
+ return nil, "", nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef))
}
ref, err := is.Transport.ParseStoreReference(store, destImage)
if err != nil {
- return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", destImage)
+ return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", destImage)
}
img, err := is.Transport.GetStoreImage(store, ref)
if err == nil {
- return ref, img, nil
+ return ref, transport, img, nil
}
if errors.Cause(err) == storage.ErrImageUnknown && options.PullPolicy != PullIfMissing {
@@ -187,26 +187,26 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
continue
}
- pulledImg, pulledReference, err := pullAndFindImage(ctx, store, image, options, systemContext)
+ pulledImg, pulledReference, err := pullAndFindImage(ctx, store, transport, image, options, systemContext)
if err != nil {
logrus.Debugf("unable to pull and read image %q: %v", image, err)
failures = append(failures, failure{resolvedImageName: image, err: err})
continue
}
- return pulledReference, pulledImg, nil
+ return pulledReference, transport, pulledImg, nil
}
if len(failures) != len(candidates) {
- return nil, nil, fmt.Errorf("internal error: %d candidates (%#v) vs. %d failures (%#v)", len(candidates), candidates, len(failures), failures)
+ return nil, "", nil, fmt.Errorf("internal error: %d candidates (%#v) vs. %d failures (%#v)", len(candidates), candidates, len(failures), failures)
}
registriesConfPath := sysregistries.RegistriesConfPath(systemContext)
switch len(failures) {
case 0:
if searchRegistriesWereUsedButEmpty {
- return nil, nil, errors.Errorf("image name %q is a short name and no search registries are defined in %s.", options.FromImage, registriesConfPath)
+ return nil, "", nil, errors.Errorf("image name %q is a short name and no search registries are defined in %s.", options.FromImage, registriesConfPath)
}
- return nil, nil, fmt.Errorf("internal error: no pull candidates were available for %q for an unknown reason", options.FromImage)
+ return nil, "", nil, fmt.Errorf("internal error: no pull candidates were available for %q for an unknown reason", options.FromImage)
case 1:
err := failures[0].err
@@ -216,7 +216,7 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
if searchRegistriesWereUsedButEmpty {
err = errors.Wrapf(err, "(image name %q is a short name and no search registries are defined in %s)", options.FromImage, registriesConfPath)
}
- return nil, nil, err
+ return nil, "", nil, err
default:
// NOTE: a multi-line error string:
@@ -224,7 +224,7 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
for _, f := range failures {
e = e + fmt.Sprintf("\n* %q: %s", f.resolvedImageName, f.err.Error())
}
- return nil, nil, errors.New(e)
+ return nil, "", nil, errors.New(e)
}
}
@@ -250,21 +250,19 @@ func findUnusedContainer(name string, containers []storage.Container) string {
}
func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions) (*Builder, error) {
- var ref types.ImageReference
- var img *storage.Image
- var err error
-
+ var (
+ ref types.ImageReference
+ img *storage.Image
+ err error
+ )
if options.FromImage == BaseImageFakeName {
options.FromImage = ""
}
- if options.Transport == "" {
- options.Transport = util.DefaultTransport
- }
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
if options.FromImage != "" && options.FromImage != "scratch" {
- ref, img, err = resolveImage(ctx, systemContext, store, options)
+ ref, _, img, err = resolveImage(ctx, systemContext, store, options)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go
index bbbbf3476..09f951b35 100644
--- a/vendor/github.com/containers/buildah/pkg/cli/common.go
+++ b/vendor/github.com/containers/buildah/pkg/cli/common.go
@@ -55,20 +55,21 @@ type BudResults struct {
File []string
Format string
Iidfile string
- NoCache bool
Label []string
Logfile string
Loglevel int
+ NoCache bool
Platform string
Pull bool
PullAlways bool
Quiet bool
Rm bool
Runtime string
- RuntimeOpts []string
+ RuntimeFlags []string
SignaturePolicy string
Squash bool
Tag []string
+ Target string
TlsVerify bool
}
@@ -138,7 +139,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.StringVar(&flags.CertDir, "cert-dir", "", "use certificates at the specified path to access the registry")
fs.BoolVar(&flags.Compress, "compress", false, "This is legacy option, which has no effect on the image")
fs.StringVar(&flags.Creds, "creds", "", "use `[username[:password]]` for accessing the registry")
- fs.BoolVarP(&flags.DisableCompression, "disable-compression", "D", false, "don't compress layers by default")
+ fs.BoolVarP(&flags.DisableCompression, "disable-compression", "D", true, "don't compress layers by default")
fs.BoolVar(&flags.DisableContentTrust, "disable-content-trust", false, "This is a Docker specific option and is a NOOP")
fs.StringSliceVarP(&flags.File, "file", "f", []string{}, "`pathname or URL` of a Dockerfile")
fs.StringVar(&flags.Format, "format", DefaultFormat(), "`format` of the built image's manifest and metadata. Use BUILDAH_FORMAT environment variable to override.")
@@ -153,10 +154,11 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.BoolVarP(&flags.Quiet, "quiet", "q", false, "refrain from announcing build instructions and image read/write progress")
fs.BoolVar(&flags.Rm, "rm", true, "Remove intermediate containers after a successful build (default true)")
fs.StringVar(&flags.Runtime, "runtime", util.Runtime(), "`path` to an alternate runtime. Use BUILDAH_RUNTIME environment variable to override.")
- fs.StringSliceVar(&flags.RuntimeOpts, "runtime-flag", []string{}, "add global flags for the container runtime")
+ fs.StringSliceVar(&flags.RuntimeFlags, "runtime-flag", []string{}, "add global flags for the container runtime")
fs.StringVar(&flags.SignaturePolicy, "signature-policy", "", "`pathname` of signature policy file (not usually used)")
fs.BoolVar(&flags.Squash, "squash", false, "Squash newly built layers into a single new layer. The build process does not currently support caching so this is a NOOP.")
fs.StringSliceVarP(&flags.Tag, "tag", "t", []string{}, "tagged `name` to apply to the built image")
+ fs.StringVar(&flags.Target, "target", "", "set the target build stage to build")
fs.BoolVar(&flags.TlsVerify, "tls-verify", true, "require HTTPS and verify certificates when accessing the registry")
return fs
}
diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse.go b/vendor/github.com/containers/buildah/pkg/parse/parse.go
index ffc7c15bb..a26d15631 100644
--- a/vendor/github.com/containers/buildah/pkg/parse/parse.go
+++ b/vendor/github.com/containers/buildah/pkg/parse/parse.go
@@ -251,9 +251,9 @@ func SystemContextFromOptions(c *cobra.Command) (*types.SystemContext, error) {
}
tlsVerify, err := c.Flags().GetBool("tls-verify")
if err == nil && c.Flag("tls-verify").Changed {
- ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(tlsVerify)
- ctx.OCIInsecureSkipTLSVerify = tlsVerify
- ctx.DockerDaemonInsecureSkipTLSVerify = tlsVerify
+ ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!tlsVerify)
+ ctx.OCIInsecureSkipTLSVerify = !tlsVerify
+ ctx.DockerDaemonInsecureSkipTLSVerify = !tlsVerify
}
creds, err := c.Flags().GetString("creds")
if err == nil && c.Flag("creds").Changed {
diff --git a/vendor/github.com/containers/buildah/pull.go b/vendor/github.com/containers/buildah/pull.go
index aede1784b..d1f33fb01 100644
--- a/vendor/github.com/containers/buildah/pull.go
+++ b/vendor/github.com/containers/buildah/pull.go
@@ -9,10 +9,13 @@ import (
"github.com/containers/buildah/pkg/blobcache"
"github.com/containers/buildah/util"
cp "github.com/containers/image/copy"
+ "github.com/containers/image/directory"
"github.com/containers/image/docker"
+ dockerarchive "github.com/containers/image/docker/archive"
"github.com/containers/image/docker/reference"
tarfile "github.com/containers/image/docker/tarfile"
ociarchive "github.com/containers/image/oci/archive"
+ oci "github.com/containers/image/oci/layout"
"github.com/containers/image/signature"
is "github.com/containers/image/storage"
"github.com/containers/image/transports"
@@ -40,10 +43,6 @@ type PullOptions struct {
// github.com/containers/image/types SystemContext to hold credentials
// and other authentication/authorization information.
SystemContext *types.SystemContext
- // Transport is a value which is prepended to the image's name, if the
- // image name alone can not be resolved to a reference to a source
- // image. No separator is implicitly added.
- Transport string
// BlobDirectory is the name of a directory in which we'll attempt to
// store copies of layer blobs that we pull down, if any. It should
// already exist.
@@ -51,10 +50,6 @@ type PullOptions struct {
// AllTags is a boolean value that determines if all tagged images
// will be downloaded from the repository. The default is false.
AllTags bool
- // Quiet is a boolean value that determines if minimal output to
- // the user will be displayed, this is best used for logging.
- // The default is false.
- Quiet bool
}
func localImageNameForReference(ctx context.Context, store storage.Store, srcRef types.ImageReference, spec string) (string, error) {
@@ -65,7 +60,7 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef
file := split[len(split)-1]
var name string
switch srcRef.Transport().Name() {
- case util.DockerArchive:
+ case dockerarchive.Transport.Name():
tarSource, err := tarfile.NewSourceFromFile(file)
if err != nil {
return "", errors.Wrapf(err, "error opening tarfile %q as a source image", file)
@@ -92,7 +87,7 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef
}
}
}
- case util.OCIArchive:
+ case ociarchive.Transport.Name():
// retrieve the manifest from index.json to access the image name
manifest, err := ociarchive.LoadManifestDescriptor(srcRef)
if err != nil {
@@ -107,7 +102,14 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef
} else {
name = manifest.Annotations["org.opencontainers.image.ref.name"]
}
- case util.DirTransport:
+ case directory.Transport.Name():
+ // supports pull from a directory
+ name = split[1]
+ // remove leading "/"
+ if name[:1] == "/" {
+ name = name[1:]
+ }
+ case oci.Transport.Name():
// supports pull from a directory
name = split[1]
// remove leading "/"
@@ -152,76 +154,71 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef
// Pull copies the contents of the image from somewhere else to local storage.
func Pull(ctx context.Context, imageName string, options PullOptions) error {
- spec := imageName
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
- srcRef, err := alltransports.ParseImageName(spec)
- if err != nil {
- if options.Transport == "" {
- options.Transport = util.DefaultTransport
- }
- logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, options.Transport, err)
- transport := options.Transport
- if transport != util.DefaultTransport {
- transport = transport + ":"
- }
- spec = transport + spec
- srcRef2, err2 := alltransports.ParseImageName(spec)
- if err2 != nil {
- return errors.Wrapf(err2, "error parsing image name %q", imageName)
- }
- srcRef = srcRef2
+
+ boptions := BuilderOptions{
+ FromImage: imageName,
+ SignaturePolicyPath: options.SignaturePolicyPath,
+ SystemContext: systemContext,
+ PullBlobDirectory: options.BlobDirectory,
+ ReportWriter: options.ReportWriter,
}
- if options.Quiet {
- options.ReportWriter = nil // Turns off logging output
+
+ storageRef, transport, img, err := resolveImage(ctx, systemContext, options.Store, boptions)
+ if err != nil {
+ return err
}
- var names []string
+
+ var errs *multierror.Error
if options.AllTags {
- if srcRef.DockerReference() == nil {
- return errors.New("Non-docker transport is currently not supported")
+ if transport != util.DefaultTransport {
+ return errors.New("Non-docker transport is not supported, for --all-tags pulling")
+ }
+
+ spec := transport + storageRef.DockerReference().Name()
+ storageRef, err = alltransports.ParseImageName(spec)
+ if err != nil {
+ return errors.Wrapf(err, "error getting repository tags")
}
- tags, err := docker.GetRepositoryTags(ctx, systemContext, srcRef)
+ tags, err := docker.GetRepositoryTags(ctx, systemContext, storageRef)
if err != nil {
return errors.Wrapf(err, "error getting repository tags")
}
for _, tag := range tags {
name := spec + ":" + tag
- names = append(names, name)
+ if options.ReportWriter != nil {
+ options.ReportWriter.Write([]byte("Pulling " + name + "\n"))
+ }
+ ref, err := pullImage(ctx, options.Store, transport, name, options, systemContext)
+ if err != nil {
+ errs = multierror.Append(errs, err)
+ continue
+ }
+ img, err := is.Transport.GetStoreImage(options.Store, ref)
+ if err != nil {
+ errs = multierror.Append(errs, err)
+ continue
+ }
+ fmt.Printf("%s\n", img.ID)
}
} else {
- names = append(names, spec)
- }
- var errs *multierror.Error
- for _, name := range names {
- if options.ReportWriter != nil {
- options.ReportWriter.Write([]byte("Pulling " + name + "\n"))
- }
- ref, err := pullImage(ctx, options.Store, name, options, systemContext)
- if err != nil {
- errs = multierror.Append(errs, err)
- continue
- }
- img, err := is.Transport.GetStoreImage(options.Store, ref)
- if err != nil {
- errs = multierror.Append(errs, err)
- continue
- }
fmt.Printf("%s\n", img.ID)
}
return errs.ErrorOrNil()
}
-func pullImage(ctx context.Context, store storage.Store, imageName string, options PullOptions, sc *types.SystemContext) (types.ImageReference, error) {
+func pullImage(ctx context.Context, store storage.Store, transport string, imageName string, options PullOptions, sc *types.SystemContext) (types.ImageReference, error) {
spec := imageName
srcRef, err := alltransports.ParseImageName(spec)
if err != nil {
- if options.Transport == "" {
- options.Transport = util.DefaultTransport
- }
- logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, options.Transport, err)
- transport := options.Transport
- if transport != util.DefaultTransport {
- transport = transport + ":"
+ logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, transport, err)
+ if transport == "" {
+ transport = util.DefaultTransport
+ } else {
+ if transport != util.DefaultTransport {
+ transport = transport + ":"
+ }
}
spec = transport + spec
srcRef2, err2 := alltransports.ParseImageName(spec)
diff --git a/vendor/github.com/containers/buildah/unshare/unshare.c b/vendor/github.com/containers/buildah/unshare/unshare.c
index 3865e414f..8eefae41b 100644
--- a/vendor/github.com/containers/buildah/unshare/unshare.c
+++ b/vendor/github.com/containers/buildah/unshare/unshare.c
@@ -2,6 +2,8 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <linux/memfd.h>
#include <fcntl.h>
#include <grp.h>
#include <sched.h>
@@ -12,6 +14,28 @@
#include <errno.h>
#include <unistd.h>
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+#endif
+#ifndef F_SEAL_SEAL
+#define F_SEAL_SEAL 0x0001LU
+#endif
+#ifndef F_SEAL_SHRINK
+#define F_SEAL_SHRINK 0x0002LU
+#endif
+#ifndef F_SEAL_GROW
+#define F_SEAL_GROW 0x0004LU
+#endif
+#ifndef F_SEAL_WRITE
+#define F_SEAL_WRITE 0x0008LU
+#endif
+
+#define BUFSTEP 1024
+
static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces";
static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone";
@@ -59,6 +83,119 @@ static void _check_proc_sys_file(const char *path)
}
}
+static char **parse_proc_stringlist(const char *list) {
+ int fd, n, i, n_strings;
+ char *buf, *new_buf, **ret;
+ size_t size, new_size, used;
+
+ fd = open(list, O_RDONLY);
+ if (fd == -1) {
+ return NULL;
+ }
+ buf = NULL;
+ size = 0;
+ used = 0;
+ for (;;) {
+ new_size = used + BUFSTEP;
+ new_buf = realloc(buf, new_size);
+ if (new_buf == NULL) {
+ free(buf);
+ fprintf(stderr, "realloc(%ld): out of memory\n", (long)(size + BUFSTEP));
+ return NULL;
+ }
+ buf = new_buf;
+ size = new_size;
+ memset(buf + used, '\0', size - used);
+ n = read(fd, buf + used, size - used - 1);
+ if (n < 0) {
+ fprintf(stderr, "read(): %m\n");
+ return NULL;
+ }
+ if (n == 0) {
+ break;
+ }
+ used += n;
+ }
+ close(fd);
+ n_strings = 0;
+ for (n = 0; n < used; n++) {
+ if ((n == 0) || (buf[n-1] == '\0')) {
+ n_strings++;
+ }
+ }
+ ret = calloc(n_strings + 1, sizeof(char *));
+ if (ret == NULL) {
+ fprintf(stderr, "calloc(): out of memory\n");
+ return NULL;
+ }
+ i = 0;
+ for (n = 0; n < used; n++) {
+ if ((n == 0) || (buf[n-1] == '\0')) {
+ ret[i++] = &buf[n];
+ }
+ }
+ ret[i] = NULL;
+ return ret;
+}
+
+static int buildah_reexec(void) {
+ char **argv, *exename;
+ int fd, mmfd, n_read, n_written;
+ struct stat st;
+ char buf[2048];
+
+ argv = parse_proc_stringlist("/proc/self/cmdline");
+ if (argv == NULL) {
+ return -1;
+ }
+ fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ fprintf(stderr, "open(\"/proc/self/exe\"): %m\n");
+ return -1;
+ }
+ if (fstat(fd, &st) == -1) {
+ fprintf(stderr, "fstat(\"/proc/self/exe\"): %m\n");
+ return -1;
+ }
+ exename = basename(argv[0]);
+ mmfd = syscall(SYS_memfd_create, exename, (long) MFD_ALLOW_SEALING | MFD_CLOEXEC);
+ if (mmfd == -1) {
+ fprintf(stderr, "memfd_create(): %m\n");
+ return -1;
+ }
+ for (;;) {
+ n_read = read(fd, buf, sizeof(buf));
+ if (n_read < 0) {
+ fprintf(stderr, "read(\"/proc/self/exe\"): %m\n");
+ return -1;
+ }
+ if (n_read == 0) {
+ break;
+ }
+ n_written = write(mmfd, buf, n_read);
+ if (n_written < 0) {
+ fprintf(stderr, "write(anonfd): %m\n");
+ return -1;
+ }
+ if (n_written != n_read) {
+ fprintf(stderr, "write(anonfd): short write (%d != %d)\n", n_written, n_read);
+ return -1;
+ }
+ }
+ close(fd);
+ if (fcntl(mmfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) == -1) {
+ close(mmfd);
+ fprintf(stderr, "Error sealing memfd copy: %m\n");
+ return -1;
+ }
+ if (fexecve(mmfd, argv, environ) == -1) {
+ close(mmfd);
+ fprintf(stderr, "Error during reexec(...): %m\n");
+ return -1;
+ }
+ return 0;
+}
+
void _buildah_unshare(void)
{
int flags, pidfd, continuefd, n, pgrp, sid, ctty;
@@ -132,5 +269,8 @@ void _buildah_unshare(void)
_exit(1);
}
}
+ if (buildah_reexec() != 0) {
+ _exit(1);
+ }
return;
}
diff --git a/vendor/github.com/containers/buildah/unshare/unshare.go b/vendor/github.com/containers/buildah/unshare/unshare.go
index 2a970b8d6..1072c2035 100644
--- a/vendor/github.com/containers/buildah/unshare/unshare.go
+++ b/vendor/github.com/containers/buildah/unshare/unshare.go
@@ -56,8 +56,10 @@ func (c *Cmd) Start() error {
c.Env = append(c.Env, fmt.Sprintf("_Buildah-unshare=%d", c.UnshareFlags))
// Please the libpod "rootless" package to find the expected env variables.
- c.Env = append(c.Env, "_LIBPOD_USERNS_CONFIGURED=done")
- c.Env = append(c.Env, fmt.Sprintf("_LIBPOD_ROOTLESS_UID=%d", os.Geteuid()))
+ if os.Geteuid() != 0 {
+ c.Env = append(c.Env, "_LIBPOD_USERNS_CONFIGURED=done")
+ c.Env = append(c.Env, fmt.Sprintf("_LIBPOD_ROOTLESS_UID=%d", os.Geteuid()))
+ }
// Create the pipe for reading the child's PID.
pidRead, pidWrite, err := os.Pipe()
diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go
index e46f9b7cb..d98493634 100644
--- a/vendor/github.com/containers/buildah/util/util.go
+++ b/vendor/github.com/containers/buildah/util/util.go
@@ -11,14 +11,11 @@ import (
"strings"
"syscall"
- "github.com/containers/image/directory"
- dockerarchive "github.com/containers/image/docker/archive"
"github.com/containers/image/docker/reference"
- ociarchive "github.com/containers/image/oci/archive"
"github.com/containers/image/pkg/sysregistriesv2"
"github.com/containers/image/signature"
is "github.com/containers/image/storage"
- "github.com/containers/image/tarball"
+ "github.com/containers/image/transports"
"github.com/containers/image/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
@@ -43,36 +40,18 @@ var (
"index.docker.io": "library",
"docker.io": "library",
}
- // Transports contains the possible transports used for images
- Transports = map[string]string{
- dockerarchive.Transport.Name(): "",
- ociarchive.Transport.Name(): "",
- directory.Transport.Name(): "",
- tarball.Transport.Name(): "",
- }
- // DockerArchive is the transport we prepend to an image name
- // when saving to docker-archive
- DockerArchive = dockerarchive.Transport.Name()
- // OCIArchive is the transport we prepend to an image name
- // when saving to oci-archive
- OCIArchive = ociarchive.Transport.Name()
- // DirTransport is the transport for pushing and pulling
- // images to and from a directory
- DirTransport = directory.Transport.Name()
- // TarballTransport is the transport for importing a tar archive
- // and creating a filesystem image
- TarballTransport = tarball.Transport.Name()
)
// ResolveName checks if name is a valid image name, and if that name doesn't
// include a domain portion, returns a list of the names which it might
-// correspond to in the set of configured registries,
-// and a boolean which is true iff 1) the list of search registries was used, and 2) it was empty.
+// correspond to in the set of configured registries, the transport used to
+// pull the image, and a boolean which is true iff
+// 1) the list of search registries was used, and 2) it was empty.
// NOTE: The "list of search registries is empty" check does not count blocked registries,
// and neither the implied "localhost" nor a possible firstRegistry are counted
-func ResolveName(name string, firstRegistry string, sc *types.SystemContext, store storage.Store) ([]string, bool, error) {
+func ResolveName(name string, firstRegistry string, sc *types.SystemContext, store storage.Store) ([]string, string, bool, error) {
if name == "" {
- return nil, false, nil
+ return nil, "", false, nil
}
// Maybe it's a truncated image ID. Don't prepend a registry name, then.
@@ -80,27 +59,28 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
if img, err := store.Image(name); err == nil && img != nil && strings.HasPrefix(img.ID, name) {
// It's a truncated version of the ID of an image that's present in local storage;
// we need only expand the ID.
- return []string{img.ID}, false, nil
+ return []string{img.ID}, "", false, nil
}
}
// If the image includes a transport's name as a prefix, use it as-is.
+ if strings.HasPrefix(name, DefaultTransport) {
+ return []string{strings.TrimPrefix(name, DefaultTransport)}, DefaultTransport, false, nil
+ }
split := strings.SplitN(name, ":", 2)
if len(split) == 2 {
- if _, ok := Transports[split[0]]; ok {
- return []string{split[1]}, false, nil
+ if trans := transports.Get(split[0]); trans != nil {
+ return []string{split[1]}, trans.Name(), false, nil
}
}
-
- name = strings.TrimPrefix(name, DefaultTransport)
// If the image name already included a domain component, we're done.
named, err := reference.ParseNormalizedNamed(name)
if err != nil {
- return nil, false, errors.Wrapf(err, "error parsing image name %q", name)
+ return nil, "", false, errors.Wrapf(err, "error parsing image name %q", name)
}
if named.String() == name {
// Parsing produced the same result, so there was a domain name in there to begin with.
- return []string{name}, false, nil
+ return []string{name}, DefaultTransport, false, nil
}
if reference.Domain(named) != "" && RegistryDefaultPathPrefix[reference.Domain(named)] != "" {
// If this domain can cause us to insert something in the middle, check if that happened.
@@ -117,7 +97,7 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
defaultPrefix := RegistryDefaultPathPrefix[reference.Domain(named)] + "/"
if strings.HasPrefix(repoPath, defaultPrefix) && path.Join(domain, repoPath[len(defaultPrefix):])+tag+digest == name {
// Yup, parsing just inserted a bit in the middle, so there was a domain name there to begin with.
- return []string{name}, false, nil
+ return []string{name}, DefaultTransport, false, nil
}
}
@@ -153,7 +133,7 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
candidate := path.Join(registry, middle, name)
candidates = append(candidates, candidate)
}
- return candidates, searchRegistriesAreEmpty, nil
+ return candidates, DefaultTransport, searchRegistriesAreEmpty, nil
}
// ExpandNames takes unqualified names, parses them as image names, and returns
@@ -164,7 +144,7 @@ func ExpandNames(names []string, firstRegistry string, systemContext *types.Syst
expanded := make([]string, 0, len(names))
for _, n := range names {
var name reference.Named
- nameList, _, err := ResolveName(n, firstRegistry, systemContext, store)
+ nameList, _, _, err := ResolveName(n, firstRegistry, systemContext, store)
if err != nil {
return nil, errors.Wrapf(err, "error parsing name %q", n)
}
@@ -200,7 +180,7 @@ func FindImage(store storage.Store, firstRegistry string, systemContext *types.S
var ref types.ImageReference
var img *storage.Image
var err error
- names, _, err := ResolveName(image, firstRegistry, systemContext, store)
+ names, _, _, err := ResolveName(image, firstRegistry, systemContext, store)
if err != nil {
return nil, nil, errors.Wrapf(err, "error parsing name %q", image)
}
diff --git a/vendor/github.com/containers/buildah/vendor.conf b/vendor/github.com/containers/buildah/vendor.conf
index bda5f3965..7438fc909 100644
--- a/vendor/github.com/containers/buildah/vendor.conf
+++ b/vendor/github.com/containers/buildah/vendor.conf
@@ -3,10 +3,13 @@ github.com/blang/semver v3.5.0
github.com/BurntSushi/toml v0.2.0
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-alpha1
-github.com/containers/image v1.3
+github.com/containers/image v1.4
+github.com/vbauerster/mpb v3.3.4
+github.com/mattn/go-isatty v0.0.4
+github.com/VividCortex/ewma v1.1.1
github.com/boltdb/bolt v1.3.1
github.com/containers/libpod v1.0
-github.com/containers/storage v1.9
+github.com/containers/storage v1.10
github.com/docker/distribution 5f6282db7d65e6d72ad7c2cc66310724a57be716
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
github.com/docker/docker-credential-helpers v0.6.1
@@ -21,7 +24,6 @@ github.com/gorilla/mux v1.6.2
github.com/hashicorp/errwrap v1.0.0
github.com/hashicorp/go-multierror v1.0.0
github.com/imdario/mergo v0.3.6
-github.com/mattn/go-runewidth v0.0.4
github.com/mattn/go-shellwords v1.0.3
github.com/Microsoft/go-winio v0.4.11
github.com/Microsoft/hcsshim v0.8.3
@@ -36,7 +38,7 @@ github.com/opencontainers/runc v1.0.0-rc6
github.com/opencontainers/runtime-spec v1.0.0
github.com/opencontainers/runtime-tools v0.8.0
github.com/opencontainers/selinux v1.1
-github.com/openshift/imagebuilder a4122153148e3b34161191f868565d8dffe65a69
+github.com/openshift/imagebuilder 36823496a6868f72bc36282cc475eb8a070c0934
github.com/ostreedev/ostree-go 9ab99253d365aac3a330d1f7281cf29f3d22820b
github.com/pkg/errors v0.8.1
github.com/pquerna/ffjson d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac
@@ -55,7 +57,6 @@ golang.org/x/net 45ffb0cd1ba084b73e26dee67e667e1be5acce83 https://github.com/gol
golang.org/x/sync 37e7f081c4d4c64e13b10787722085407fe5d15f https://github.com/golang/sync
golang.org/x/sys 7fbe1cd0fcc20051e1fcb87fbabec4a1bacaaeba https://github.com/golang/sys
golang.org/x/text e6919f6577db79269a6443b9dc46d18f2238fb5d https://github.com/golang/text
-gopkg.in/cheggaaa/pb.v1 v1.0.27
gopkg.in/yaml.v2 v2.2.2
k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go
github.com/klauspost/pgzip v1.2.1
@@ -63,17 +64,4 @@ github.com/klauspost/compress v1.4.1
github.com/klauspost/cpuid v1.2.0
github.com/onsi/gomega v1.4.3
github.com/spf13/cobra v0.0.3
-github.com/cpuguy83/go-md2man v1.0.8
github.com/spf13/pflag v1.0.3
-github.com/inconshreveable/mousetrap v1.0.0
-github.com/russross/blackfriday v2.0.1
-github.com/mitchellh/go-homedir v1.0.0
-github.com/spf13/viper v1.3.1
-github.com/fsnotify/fsnotify v1.4.7
-github.com/hashicorp/hcl v1.0.0
-github.com/magiconair/properties v1.8.0
-github.com/mitchellh/mapstructure v1.1.2
-github.com/pelletier/go-toml v1.2.0
-github.com/spf13/afero v1.2.0
-github.com/spf13/cast v1.3.0
-github.com/spf13/jwalterweatherman v1.0.0
diff --git a/vendor/github.com/openshift/imagebuilder/README.md b/vendor/github.com/openshift/imagebuilder/README.md
index 2f9c110dd..f26b4a7e0 100644
--- a/vendor/github.com/openshift/imagebuilder/README.md
+++ b/vendor/github.com/openshift/imagebuilder/README.md
@@ -70,7 +70,7 @@ is ignored.
## Code Example
-```
+```go
f, err := os.Open("path/to/Dockerfile")
if err != nil {
return err
diff --git a/vendor/github.com/openshift/imagebuilder/builder.go b/vendor/github.com/openshift/imagebuilder/builder.go
index d37965df6..16682af7d 100644
--- a/vendor/github.com/openshift/imagebuilder/builder.go
+++ b/vendor/github.com/openshift/imagebuilder/builder.go
@@ -40,6 +40,7 @@ type Run struct {
type Executor interface {
Preserve(path string) error
+ EnsureContainerPath(path string) error
Copy(excludes []string, copies ...Copy) error
Run(run Run, config docker.Config) error
UnrecognizedInstruction(step *Step) error
@@ -52,6 +53,11 @@ func (logExecutor) Preserve(path string) error {
return nil
}
+func (logExecutor) EnsureContainerPath(path string) error {
+ log.Printf("ENSURE %s", path)
+ return nil
+}
+
func (logExecutor) Copy(excludes []string, copies ...Copy) error {
for _, c := range copies {
log.Printf("COPY %v -> %s (from:%s download:%t), chown: %s", c.Src, c.Dest, c.From, c.Download, c.Chown)
@@ -75,6 +81,10 @@ func (noopExecutor) Preserve(path string) error {
return nil
}
+func (noopExecutor) EnsureContainerPath(path string) error {
+ return nil
+}
+
func (noopExecutor) Copy(excludes []string, copies ...Copy) error {
return nil
}
@@ -153,6 +163,7 @@ func (stages Stages) ByName(name string) (Stage, bool) {
return Stage{}, false
}
+// Get just the target stage.
func (stages Stages) ByTarget(target string) (Stages, bool) {
if len(target) == 0 {
return stages, true
@@ -165,6 +176,19 @@ func (stages Stages) ByTarget(target string) (Stages, bool) {
return nil, false
}
+// Get all the stages up to and including the target.
+func (stages Stages) ThroughTarget(target string) (Stages, bool) {
+ if len(target) == 0 {
+ return stages, true
+ }
+ for i, stage := range stages {
+ if stage.Name == target {
+ return stages[0 : i+1], true
+ }
+ }
+ return nil, false
+}
+
type Stage struct {
Position int
Name string
@@ -319,6 +343,13 @@ func (b *Builder) Run(step *Step, exec Executor, noRunsRemaining bool) error {
if err := exec.Copy(b.Excludes, copies...); err != nil {
return err
}
+
+ if len(b.RunConfig.WorkingDir) > 0 {
+ if err := exec.EnsureContainerPath(b.RunConfig.WorkingDir); err != nil {
+ return err
+ }
+ }
+
for _, run := range runs {
config := b.Config()
config.Env = step.Env
diff --git a/vendor/github.com/openshift/imagebuilder/dispatchers.go b/vendor/github.com/openshift/imagebuilder/dispatchers.go
index f6510c2fd..ff365848a 100644
--- a/vendor/github.com/openshift/imagebuilder/dispatchers.go
+++ b/vendor/github.com/openshift/imagebuilder/dispatchers.go
@@ -128,9 +128,20 @@ func add(b *Builder, args []string, attributes map[string]bool, flagArgs []strin
if len(args) < 2 {
return errAtLeastOneArgument("ADD")
}
+ var chown string
last := len(args) - 1
dest := makeAbsolute(args[last], b.RunConfig.WorkingDir)
- b.PendingCopies = append(b.PendingCopies, Copy{Src: args[0:last], Dest: dest, Download: true})
+ if len(flagArgs) > 0 {
+ for _, arg := range flagArgs {
+ switch {
+ case strings.HasPrefix(arg, "--chown="):
+ chown = strings.TrimPrefix(arg, "--chown=")
+ default:
+ return fmt.Errorf("ADD only supports the --chown=<uid:gid> flag")
+ }
+ }
+ }
+ b.PendingCopies = append(b.PendingCopies, Copy{Src: args[0:last], Dest: dest, Download: true, Chown: chown})
return nil
}