summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml2
-rw-r--r--Makefile8
-rw-r--r--cmd/podman/common/completion.go10
-rw-r--r--cmd/podman/common/create.go2
-rw-r--r--cmd/podman/containers/checkpoint.go10
-rw-r--r--cmd/podman/containers/ps.go5
-rw-r--r--cmd/podman/containers/restore.go11
-rw-r--r--cmd/podman/images/build.go10
-rw-r--r--cmd/podman/images/search.go47
-rw-r--r--cmd/podman/play/kube.go15
-rw-r--r--cmd/podman/pods/ps.go5
-rw-r--r--cmd/podman/root.go2
-rwxr-xr-xcontrib/cirrus/runner.sh3
-rw-r--r--docs/source/markdown/podman-build.1.md13
-rw-r--r--docs/source/markdown/podman-container-checkpoint.1.md20
-rw-r--r--docs/source/markdown/podman-container-restore.1.md14
-rw-r--r--docs/source/markdown/podman-pod-ps.1.md3
-rw-r--r--docs/source/markdown/podman-ps.1.md2
-rw-r--r--docs/source/markdown/podman.1.md2
-rw-r--r--docs/tutorials/podman_tutorial.md2
-rw-r--r--docs/tutorials/rootless_tutorial.md2
-rw-r--r--go.mod8
-rw-r--r--go.sum32
-rw-r--r--libpod/container_api.go16
-rw-r--r--libpod/container_exec.go10
-rw-r--r--libpod/container_internal.go11
-rw-r--r--libpod/container_internal_linux.go136
-rw-r--r--libpod/container_log.go2
-rw-r--r--libpod/networking_linux.go2
-rw-r--r--libpod/oci.go4
-rw-r--r--libpod/oci_attach_linux.go29
-rw-r--r--libpod/oci_attach_linux_cgo.go11
-rw-r--r--libpod/oci_attach_linux_nocgo.go7
-rw-r--r--libpod/oci_conmon_exec_linux.go10
-rw-r--r--libpod/oci_conmon_linux.go62
-rw-r--r--libpod/options.go2
-rw-r--r--pkg/api/handlers/compat/containers_prune.go44
-rw-r--r--pkg/api/handlers/compat/images.go47
-rw-r--r--pkg/api/handlers/compat/images_prune.go75
-rw-r--r--pkg/api/handlers/compat/volumes.go28
-rw-r--r--pkg/api/handlers/libpod/containers.go1
-rw-r--r--pkg/api/handlers/libpod/pods.go11
-rw-r--r--pkg/api/handlers/libpod/system.go4
-rw-r--r--pkg/api/handlers/utils/pods.go87
-rw-r--r--pkg/api/server/docs.go2
-rw-r--r--pkg/api/server/register_networks.go13
-rw-r--r--pkg/checkpoint/checkpoint_restore.go29
-rw-r--r--pkg/domain/entities/container_ps.go2
-rw-r--r--pkg/domain/entities/containers.go5
-rw-r--r--pkg/domain/entities/play.go3
-rw-r--r--pkg/domain/entities/pods.go6
-rw-r--r--pkg/domain/filters/containers.go19
-rw-r--r--pkg/domain/filters/pods.go24
-rw-r--r--pkg/domain/infra/abi/containers.go7
-rw-r--r--pkg/domain/infra/abi/images_list.go5
-rw-r--r--pkg/domain/infra/abi/play.go17
-rw-r--r--pkg/domain/infra/abi/pods.go12
-rw-r--r--pkg/netns/netns_linux.go4
-rw-r--r--pkg/ps/ps.go6
-rw-r--r--pkg/rootless/rootless.go153
-rw-r--r--pkg/rootless/rootless_test.go101
-rw-r--r--pkg/signal/signal_linux_mipsx.go2
-rw-r--r--pkg/specgen/generate/container.go30
-rw-r--r--pkg/specgen/generate/security.go3
-rw-r--r--pkg/systemd/generate/containers_test.go24
-rw-r--r--pkg/systemd/generate/pods_test.go6
-rw-r--r--test/apiv2/rest_api/test_rest_v2_0_0.py62
-rw-r--r--test/e2e/build/basicalpine/Containerfile.volume2
-rw-r--r--test/e2e/checkpoint_test.go170
-rw-r--r--test/e2e/common_test.go14
-rw-r--r--test/e2e/exec_test.go190
-rw-r--r--test/e2e/pod_ps_test.go64
-rw-r--r--test/e2e/ps_test.go64
-rw-r--r--test/e2e/run_test.go29
-rw-r--r--test/e2e/search_test.go10
-rw-r--r--test/system/010-images.bats13
-rw-r--r--test/system/400-unprivileged-access.bats2
-rw-r--r--troubleshooting.md2
-rw-r--r--vendor/github.com/containers/buildah/Makefile5
-rw-r--r--vendor/github.com/containers/buildah/chroot/selinux.go2
-rw-r--r--vendor/github.com/containers/buildah/chroot/selinux_unsupported.go2
-rw-r--r--vendor/github.com/containers/buildah/go.mod6
-rw-r--r--vendor/github.com/containers/buildah/go.sum18
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/build.go3
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/executor.go9
-rw-r--r--vendor/github.com/containers/buildah/pkg/cli/common.go5
-rw-r--r--vendor/github.com/containers/buildah/selinux.go2
-rw-r--r--vendor/github.com/containers/buildah/selinux_unsupported.go2
-rw-r--r--vendor/github.com/containers/common/pkg/auth/auth.go13
-rw-r--r--vendor/github.com/containers/common/pkg/completion/completion.go48
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go13
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go2
-rw-r--r--vendor/github.com/containers/common/pkg/retry/retry.go12
-rw-r--r--vendor/github.com/containers/common/pkg/retry/retry_linux.go9
-rw-r--r--vendor/github.com/containers/common/pkg/retry/retry_unsupported.go7
-rw-r--r--vendor/github.com/containers/common/pkg/seccomp/default_linux.go1
-rw-r--r--vendor/github.com/containers/common/pkg/seccomp/seccomp.json1
-rw-r--r--vendor/github.com/containers/common/version/version.go2
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go28
-rw-r--r--vendor/github.com/containers/storage/go.mod2
-rw-r--r--vendor/github.com/containers/storage/go.sum4
-rw-r--r--vendor/github.com/containers/storage/pkg/idtools/idtools.go22
-rw-r--r--vendor/github.com/containers/storage/store.go5
-rw-r--r--vendor/github.com/containers/storage/utils.go25
-rw-r--r--vendor/github.com/google/uuid/uuid.go6
-rw-r--r--vendor/github.com/klauspost/compress/zstd/decoder.go20
-rw-r--r--vendor/github.com/klauspost/compress/zstd/seqdec.go15
-rw-r--r--vendor/github.com/klauspost/compress/zstd/zstd.go4
-rw-r--r--vendor/modules.txt10
110 files changed, 1780 insertions, 447 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 18cb889ad..3eaa4ede8 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -311,6 +311,8 @@ alt_build_task:
ALT_NAME: 'Build Without CGO'
- env:
ALT_NAME: 'Test build RPM'
+ - env:
+ ALT_NAME: 'Alt Arch. Cross'
setup_script: *setup
main_script: *main
always: *binary_artifacts
diff --git a/Makefile b/Makefile
index 5f058a710..085af6d80 100644
--- a/Makefile
+++ b/Makefile
@@ -106,7 +106,11 @@ CROSS_BUILD_TARGETS := \
bin/podman.cross.linux.arm \
bin/podman.cross.linux.arm64 \
bin/podman.cross.linux.386 \
- bin/podman.cross.linux.s390x
+ bin/podman.cross.linux.s390x \
+ bin/podman.cross.linux.mips \
+ bin/podman.cross.linux.mipsle \
+ bin/podman.cross.linux.mips64 \
+ bin/podman.cross.linux.mips64le
.PHONY: all
all: binaries docs
@@ -221,7 +225,7 @@ bin/podman.cross.%: .gopathok
TARGET="$*"; \
GOOS="$${TARGET%%.*}" \
GOARCH="$${TARGET##*.}" \
- $(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags '$(BUILDTAGS_CROSS)' -o "$@" ./cmd/podman
+ CGO_ENABLED=0 $(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags '$(BUILDTAGS_CROSS)' -o "$@" ./cmd/podman
# Update nix/nixpkgs.json its latest stable commit
.PHONY: nixpkgs
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 83fe0723c..d01842998 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -982,9 +982,10 @@ func AutocompletePsFilters(cmd *cobra.Command, args []string, toComplete string)
return []string{define.HealthCheckHealthy,
define.HealthCheckUnhealthy}, cobra.ShellCompDirectiveNoFileComp
},
- "label=": nil,
- "exited=": nil,
- "until=": nil,
+ "network=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s) },
+ "label=": nil,
+ "exited=": nil,
+ "until=": nil,
}
return completeKeyValues(toComplete, kv)
}
@@ -1004,7 +1005,8 @@ func AutocompletePodPsFilters(cmd *cobra.Command, args []string, toComplete stri
"ctr-status=": func(_ string) ([]string, cobra.ShellCompDirective) {
return containerStatuses, cobra.ShellCompDirectiveNoFileComp
},
- "label=": nil,
+ "network=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s) },
+ "label=": nil,
}
return completeKeyValues(toComplete, kv)
}
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index bbd4f6bae..24703eda2 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -336,7 +336,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
createFlags.BoolVar(
&cf.HTTPProxy,
- "http-proxy", true,
+ "http-proxy", containerConfig.Containers.HTTPProxy,
"Set proxy environment variables in the container based on the host proxy vars",
)
diff --git a/cmd/podman/containers/checkpoint.go b/cmd/podman/containers/checkpoint.go
index b6dc21348..14abfd5a7 100644
--- a/cmd/podman/containers/checkpoint.go
+++ b/cmd/podman/containers/checkpoint.go
@@ -57,6 +57,10 @@ func init() {
_ = checkpointCommand.RegisterFlagCompletionFunc(exportFlagName, completion.AutocompleteDefault)
flags.BoolVar(&checkpointOptions.IgnoreRootFS, "ignore-rootfs", false, "Do not include root file-system changes when exporting")
+ flags.BoolVar(&checkpointOptions.IgnoreVolumes, "ignore-volumes", false, "Do not export volumes associated with container")
+ flags.BoolVarP(&checkpointOptions.PreCheckPoint, "pre-checkpoint", "P", false, "Dump container's memory information only, leave the container running")
+ flags.BoolVar(&checkpointOptions.WithPrevious, "with-previous", false, "Checkpoint container with pre-checkpoint images")
+
validate.AddLatestFlag(checkpointCommand, &checkpointOptions.Latest)
}
@@ -68,6 +72,12 @@ func checkpoint(cmd *cobra.Command, args []string) error {
if checkpointOptions.Export == "" && checkpointOptions.IgnoreRootFS {
return errors.Errorf("--ignore-rootfs can only be used with --export")
}
+ if checkpointOptions.Export == "" && checkpointOptions.IgnoreVolumes {
+ return errors.Errorf("--ignore-volumes can only be used with --export")
+ }
+ if checkpointOptions.WithPrevious && checkpointOptions.PreCheckPoint {
+ return errors.Errorf("--with-previous can not be used with --pre-checkpoint")
+ }
responses, err := registry.ContainerEngine().ContainerCheckpoint(context.Background(), args, checkpointOptions)
if err != nil {
return err
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index 5d08e6163..d23771fc5 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -392,6 +392,11 @@ func (l psReporter) Names() string {
return l.ListContainer.Names[0]
}
+// Networks returns the container network names in string format
+func (l psReporter) Networks() string {
+ return strings.Join(l.ListContainer.Networks, ",")
+}
+
// Ports converts from Portmappings to the string form
// required by ps
func (l psReporter) Ports() string {
diff --git a/cmd/podman/containers/restore.go b/cmd/podman/containers/restore.go
index 6a1d2b319..49c0be88e 100644
--- a/cmd/podman/containers/restore.go
+++ b/cmd/podman/containers/restore.go
@@ -59,9 +59,14 @@ func init() {
flags.StringVarP(&restoreOptions.Name, nameFlagName, "n", "", "Specify new name for container restored from exported checkpoint (only works with --import)")
_ = restoreCommand.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone)
+ importPreviousFlagName := "import-previous"
+ flags.StringVar(&restoreOptions.ImportPrevious, importPreviousFlagName, "", "Restore from exported pre-checkpoint archive (tar.gz)")
+ _ = restoreCommand.RegisterFlagCompletionFunc(importPreviousFlagName, completion.AutocompleteDefault)
+
flags.BoolVar(&restoreOptions.IgnoreRootFS, "ignore-rootfs", false, "Do not apply root file-system changes when importing from exported checkpoint")
flags.BoolVar(&restoreOptions.IgnoreStaticIP, "ignore-static-ip", false, "Ignore IP address set via --static-ip")
flags.BoolVar(&restoreOptions.IgnoreStaticMAC, "ignore-static-mac", false, "Ignore MAC address set via --mac-address")
+ flags.BoolVar(&restoreOptions.IgnoreVolumes, "ignore-volumes", false, "Do not export volumes associated with container")
validate.AddLatestFlag(restoreCommand, &restoreOptions.Latest)
}
@@ -70,9 +75,15 @@ func restore(_ *cobra.Command, args []string) error {
if rootless.IsRootless() {
return errors.New("restoring a container requires root")
}
+ if restoreOptions.Import == "" && restoreOptions.ImportPrevious != "" {
+ return errors.Errorf("--import-previous can only be used with --import")
+ }
if restoreOptions.Import == "" && restoreOptions.IgnoreRootFS {
return errors.Errorf("--ignore-rootfs can only be used with --import")
}
+ if restoreOptions.Import == "" && restoreOptions.IgnoreVolumes {
+ return errors.Errorf("--ignore-volumes can only be used with --import")
+ }
if restoreOptions.Import == "" && restoreOptions.Name != "" {
return errors.Errorf("--name can only be used with --import")
}
diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go
index 3aca104e3..c0aa27ca1 100644
--- a/cmd/podman/images/build.go
+++ b/cmd/podman/images/build.go
@@ -135,6 +135,16 @@ func buildFlags(cmd *cobra.Command) {
logrus.Errorf("error setting up build flags: %v", err)
os.Exit(1)
}
+ // --http-proxy flag
+ // containers.conf defaults to true but we want to force false by default for remote, since settings do not apply
+ if registry.IsRemote() {
+ flag = fromAndBudFlags.Lookup("http-proxy")
+ buildOpts.HTTPProxy = false
+ if err := flag.Value.Set("false"); err != nil {
+ logrus.Errorf("unable to set --https-proxy to %v: %v", false, err)
+ }
+ flag.DefValue = "false"
+ }
flags.AddFlagSet(&fromAndBudFlags)
// Add the completion functions
fromAndBudFlagsCompletions := buildahCLI.GetFromAndBudFlagsCompletions()
diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go
index c2ef7d767..c8ea4b04a 100644
--- a/cmd/podman/images/search.go
+++ b/cmd/podman/images/search.go
@@ -26,6 +26,12 @@ type searchOptionsWrapper struct {
Format string // For go templating
}
+// listEntryTag is a utility structure used for json serialization.
+type listEntryTag struct {
+ Name string
+ Tags []string
+}
+
var (
searchOptions = searchOptionsWrapper{}
searchDescription = `Search registries for a given image. Can search all the default registries or a specific registry.
@@ -149,14 +155,13 @@ func imageSearch(cmd *cobra.Command, args []string) error {
if len(searchOptions.Filters) != 0 {
return errors.Errorf("filters are not applicable to list tags result")
}
+ if report.IsJSON(searchOptions.Format) {
+ listTagsEntries := buildListTagsJson(searchReport)
+ return printJson(listTagsEntries)
+ }
row = "{{.Name}}\t{{.Tag}}\n"
case report.IsJSON(searchOptions.Format):
- prettyJSON, err := json.MarshalIndent(searchReport, "", " ")
- if err != nil {
- return err
- }
- fmt.Println(string(prettyJSON))
- return nil
+ return printJson(searchReport)
case cmd.Flags().Changed("format"):
renderHeaders = parse.HasTable(searchOptions.Format)
row = report.NormalizeFormat(searchOptions.Format)
@@ -180,3 +185,33 @@ func imageSearch(cmd *cobra.Command, args []string) error {
return tmpl.Execute(w, searchReport)
}
+
+func printJson(v interface{}) error {
+ prettyJSON, err := json.MarshalIndent(v, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(prettyJSON))
+ return nil
+}
+
+func buildListTagsJson(searchReport []entities.ImageSearchReport) []listEntryTag {
+ entries := []listEntryTag{}
+
+ReportLoop:
+ for _, report := range searchReport {
+ for idx, entry := range entries {
+ if entry.Name == report.Name {
+ entries[idx].Tags = append(entries[idx].Tags, report.Tag)
+ continue ReportLoop
+ }
+ }
+ newElem := listEntryTag{
+ report.Name,
+ []string{report.Tag},
+ }
+
+ entries = append(entries, newElem)
+ }
+ return entries
+}
diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go
index db7280b1d..1f54db203 100644
--- a/cmd/podman/play/kube.go
+++ b/cmd/podman/play/kube.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/podman/v2/cmd/podman/utils"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/util"
+ "github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -130,6 +131,8 @@ func kube(cmd *cobra.Command, args []string) error {
}
}
+ ctrsFailed := 0
+
for _, pod := range report.Pods {
fmt.Printf("Pod:\n")
fmt.Println(pod.ID)
@@ -145,9 +148,21 @@ func kube(cmd *cobra.Command, args []string) error {
for _, ctr := range pod.Containers {
fmt.Println(ctr)
}
+ ctrsFailed += len(pod.ContainerErrors)
+ // If We have errors, add a newline
+ if len(pod.ContainerErrors) > 0 {
+ fmt.Println()
+ }
+ for _, err := range pod.ContainerErrors {
+ fmt.Fprintf(os.Stderr, err+"\n")
+ }
// Empty line for space for next block
fmt.Println()
}
+ if ctrsFailed > 0 {
+ return errors.Errorf("failed to start %d containers", ctrsFailed)
+ }
+
return nil
}
diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
index 99d324411..a27ab4859 100644
--- a/cmd/podman/pods/ps.go
+++ b/cmd/podman/pods/ps.go
@@ -191,6 +191,11 @@ func (l ListPodReporter) Labels() map[string]string {
return l.ListPodsReport.Labels
}
+// Networks returns the infra container network names in string format
+func (l ListPodReporter) Networks() string {
+ return strings.Join(l.ListPodsReport.Networks, ",")
+}
+
// NumberOfContainers returns an int representation for
// the number of containers belonging to the pod
func (l ListPodReporter) NumberOfContainers() int {
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 1f613a4c5..0ee530242 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -158,7 +158,7 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error {
// Prep the engines
if _, err := registry.NewImageEngine(cmd, args); err != nil {
- return err
+ return errors.Wrapf(err, "Cannot connect to the Podman socket, make sure there is a Podman REST API service running.")
}
if _, err := registry.NewContainerEngine(cmd, args); err != nil {
return err
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index 7f9afd1fd..e09b2af9c 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -178,6 +178,9 @@ function _run_altbuild() {
make -f ./.copr/Makefile
rpmbuild --rebuild ./podman-*.src.rpm
;;
+ Alt*Cross)
+ make local-cross
+ ;;
*Static*)
req_env_vars CTR_FQIN
[[ "$UID" -eq 0 ]] || \
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index 67513e386..32b14a267 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -294,7 +294,7 @@ If you specify `-f -`, the Containerfile contents will be read from stdin.
#### **--force-rm**=*true|false*
Always remove intermediate containers after a build, even if the build fails
-(default false).
+(default true).
#### **--format**
@@ -305,6 +305,11 @@ Recognized formats include *oci* (OCI image-spec v1.0, the default) and
Note: You can also override the default format by setting the BUILDAH\_FORMAT
environment variable. `export BUILDAH_FORMAT=docker`
+#### **--from**
+
+Overrides the first `FROM` instruction within the Containerfile. If there are multiple
+FROM instructions in a Containerfile, only the first is changed.
+
**-h**, **--help**
Print usage statement
@@ -524,6 +529,12 @@ layers are not squashed.
Squash all of the new image's layers (including those inherited from a base
image) into a single new layer.
+#### **--stdin**
+
+Pass stdin into the RUN containers. Sometime commands being RUN within a Containerfile
+want to request information from the user. For example apt asking for a confirmation for install.
+Use --stdin to be able to interact from the terminal during the build.
+
#### **--tag**, **-t**=*imageName*
Specifies the name which will be assigned to the resulting image if the build
diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md
index bfda782c5..ea05979cd 100644
--- a/docs/source/markdown/podman-container-checkpoint.1.md
+++ b/docs/source/markdown/podman-container-checkpoint.1.md
@@ -52,12 +52,32 @@ exported to a tar.gz file it is possible with the help of **--ignore-rootfs**
to explicitly disable including changes to the root file-system into
the checkpoint archive file.
+#### **--ignore-volumes**
+
+This option must be used in combination with the **--export, -e** option.
+When this option is specified, the content of volumes associated with
+the container will not be included into the checkpoint tar.gz file.
+
+#### **--pre-checkpoint**, **-P**
+
+Dump the container's memory information only, leaving the container running. Later
+operations will supersede prior dumps. It only works on runc 1.0-rc3 or higher.
+
+#### **--with-previous**
+
+Check out the container with previous criu image files in pre-dump. It only works
+without **--pre-checkpoint** or **-P**. It only works on runc 1.0-rc3 or higher.
+
## EXAMPLE
podman container checkpoint mywebserver
podman container checkpoint 860a4b23
+podman container checkpoint -P -e pre-checkpoint.tar.gz -l
+
+podman container checkpoint --with-previous -e checkpoint.tar.gz -l
+
## SEE ALSO
podman(1), podman-container-restore(1)
diff --git a/docs/source/markdown/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md
index 494e7db1e..192b8765b 100644
--- a/docs/source/markdown/podman-container-restore.1.md
+++ b/docs/source/markdown/podman-container-restore.1.md
@@ -48,6 +48,11 @@ Import a checkpoint tar.gz file, which was exported by Podman. This can be used
to import a checkpointed container from another host. Do not specify a *container*
argument when using this option.
+#### **--import-previous**
+
+Import a pre-checkpoint tar.gz file which was exported by Podman. This option
+must be used with **-i** or **--import**. It only works on runc 1.0-rc3 or higher.
+
#### **--name**, **-n**
This is only available in combination with **--import, -i**. If a container is restored
@@ -85,12 +90,21 @@ exported checkpoint with **--name, -n**.
Using **--ignore-static-mac** tells Podman to ignore the MAC address if it was
configured with **--mac-address** during container creation.
+
+#### **--ignore-volumes**
+
+This option must be used in combination with the **--import, -i** option.
+When restoring containers from a checkpoint tar.gz file with this option,
+the content of associated volumes will not be restored.
+
## EXAMPLE
podman container restore mywebserver
podman container restore 860a4b23
+podman container restore --import-previous pre-checkpoint.tar.gz --import checkpoint.tar.gz
+
## SEE ALSO
podman(1), podman-container-checkpoint(1)
diff --git a/docs/source/markdown/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md
index e1d60d765..ab250e1ff 100644
--- a/docs/source/markdown/podman-pod-ps.1.md
+++ b/docs/source/markdown/podman-pod-ps.1.md
@@ -72,6 +72,8 @@ Valid placeholders for the Go template are listed below:
| .Cgroup | Cgroup path of pod |
| .Created | Creation time of pod |
| .InfraID | Pod infra container ID |
+| .Networks | Show all networks connected to the infra container |
+
#### **--sort**
Sort by created, ID, name, status, or number of containers
@@ -93,6 +95,7 @@ Valid filters are listed below:
| name | [Name] Pod's name (accepts regex) |
| label | [Key] or [Key=Value] Label assigned to a container |
| status | Pod's status: `stopped`, `running`, `paused`, `exited`, `dead`, `created`, `degraded` |
+| network | [Network] name or full ID of network |
| ctr-names | Container name within the pod (accepts regex) |
| ctr-ids | Container ID within the pod (accepts regex) |
| ctr-status | Container status within the pod |
diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md
index 28212b92c..bb8001ad9 100644
--- a/docs/source/markdown/podman-ps.1.md
+++ b/docs/source/markdown/podman-ps.1.md
@@ -58,6 +58,7 @@ Valid filters are listed below:
| volume | [VolumeName] or [MountpointDestination] Volume mounted in container |
| health | [Status] healthy or unhealthy |
| pod | [Pod] name or full or partial ID of pod |
+| network | [Network] name or full ID of network |
#### **--format**=*format*
@@ -79,6 +80,7 @@ Valid placeholders for the Go template are listed below:
| .Ports | Exposed ports |
| .Size | Size of container |
| .Names | Name of container |
+| .Networks | Show all networks connected to the container |
| .Labels | All the labels assigned to the container |
| .Mounts | Volumes mounted in the container |
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index 2688c1720..42054d075 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -122,7 +122,7 @@ Default root dir configured in `/etc/containers/storage.conf`.
#### **--runroot**=*value*
-Storage state directory where all state information is stored (default: "/var/run/containers/storage" for UID 0, "/var/run/user/$UID/run" for other users).
+Storage state directory where all state information is stored (default: "/run/containers/storage" for UID 0, "/run/user/$UID/run" for other users).
Default state dir configured in `/etc/containers/storage.conf`.
#### **--runtime**=*value*
diff --git a/docs/tutorials/podman_tutorial.md b/docs/tutorials/podman_tutorial.md
index c15de67a6..7419f445e 100644
--- a/docs/tutorials/podman_tutorial.md
+++ b/docs/tutorials/podman_tutorial.md
@@ -21,7 +21,7 @@ For installing or building Podman, please see the [installation instructions](ht
This sample container will run a very basic httpd server that serves only its index
page.
```console
-podman run -dt -p 8080:8080/tcp -e HTTPD_VAR_RUN=/var/run/httpd -e HTTPD_MAIN_CONF_D_PATH=/etc/httpd/conf.d \
+podman run -dt -p 8080:8080/tcp -e HTTPD_VAR_RUN=/run/httpd -e HTTPD_MAIN_CONF_D_PATH=/etc/httpd/conf.d \
-e HTTPD_MAIN_CONF_PATH=/etc/httpd/conf \
-e HTTPD_CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/httpd/ \
registry.fedoraproject.org/f29/httpd /usr/bin/run-httpd
diff --git a/docs/tutorials/rootless_tutorial.md b/docs/tutorials/rootless_tutorial.md
index 9d8851bc8..cb73fc519 100644
--- a/docs/tutorials/rootless_tutorial.md
+++ b/docs/tutorials/rootless_tutorial.md
@@ -130,7 +130,7 @@ graphroot=""
Default directory to store all writable content created by container storage programs.
runroot=""
- container storage run dir (default: "/var/run/containers/storage")
+ container storage run dir (default: "/run/containers/storage")
Default directory to store all temporary writable content created by container storage programs.
```
In rootless podman these fields default to
diff --git a/go.mod b/go.mod
index 0398c5bad..15f029cce 100644
--- a/go.mod
+++ b/go.mod
@@ -10,12 +10,12 @@ require (
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
github.com/containernetworking/cni v0.8.0
github.com/containernetworking/plugins v0.9.0
- github.com/containers/buildah v1.18.1-0.20201217112226-67470615779c
- github.com/containers/common v0.31.2
+ github.com/containers/buildah v1.18.1-0.20201222143428-b9fdee076426
+ github.com/containers/common v0.33.0
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.9.0
github.com/containers/psgo v1.5.2
- github.com/containers/storage v1.24.4
+ github.com/containers/storage v1.24.5
github.com/coreos/go-systemd/v22 v22.1.0
github.com/cri-o/ocicni v0.2.1-0.20201125151022-df072ea5421c
github.com/cyphar/filepath-securejoin v0.2.2
@@ -29,7 +29,7 @@ require (
github.com/ghodss/yaml v1.0.0
github.com/godbus/dbus/v5 v5.0.3
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
- github.com/google/uuid v1.1.3
+ github.com/google/uuid v1.1.4
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
github.com/hashicorp/go-multierror v1.1.0
diff --git a/go.sum b/go.sum
index b5a64b01e..c60f1b8c0 100644
--- a/go.sum
+++ b/go.sum
@@ -23,12 +23,10 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/go-winio v0.4.15-0.20200113171025-3fe6c5262873/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
-github.com/Microsoft/go-winio v0.4.15 h1:qkLXKzb1QoVatRyd/YlXZ/Kg0m5K3SPuoD82jjSOaBc=
github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331 h1:3YnB7Hpmh1lPecPE8doMOtYCrMdrpedZOvxfuNES/Vk=
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
-github.com/Microsoft/hcsshim v0.8.9 h1:VrfodqvztU8YSOvygU+DN1BGaSGxmrNfqOv5oOuX2Bk=
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
github.com/Microsoft/hcsshim v0.8.14 h1:lbPVK25c1cu5xTLITwpUcxoA9vKrKErASPYygvouJns=
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
@@ -76,7 +74,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
-github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk=
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
@@ -96,18 +93,16 @@ github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kw
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.8.0 h1:BT9lpgGoH4jw3lFC7Odz2prU5ruiYKcgAjMCbgybcKI=
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/plugins v0.8.7 h1:bU7QieuAp+sACI2vCzESJ3FoT860urYP+lThyZkb/2M=
github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CYwm0dHzbz0XEjofx0uB0=
github.com/containernetworking/plugins v0.9.0 h1:c+1gegKhR7+d0Caum9pEHugZlyhXPOG6v3V6xJgIGCI=
github.com/containernetworking/plugins v0.9.0/go.mod h1:dbWv4dI0QrBGuVgj+TuVQ6wJRZVOhrCQj91YyC92sxg=
-github.com/containers/buildah v1.18.1-0.20201217112226-67470615779c h1:DnJiPjBKeoZbzjkUA6YMf/r5ShYpNacK+EcQ/ui1Mxo=
-github.com/containers/buildah v1.18.1-0.20201217112226-67470615779c/go.mod h1:hvIoL3urgYPL0zX8XlK05aWP6qfUnBNqTrsedsYw6OY=
-github.com/containers/common v0.31.0/go.mod h1:yT4GTUHsKRmpaDb+mecXRnIMre7W3ZgwXqaYMywXlaA=
-github.com/containers/common v0.31.2 h1:sNYwvLA4B7SpEiAWTUvkItPlCrUa2vcxh0FTKXKoC3Q=
-github.com/containers/common v0.31.2/go.mod h1:Fehe82hQfJQvDspnRrV9rcdAWG3IalNHEt0F6QWNBHQ=
+github.com/containers/buildah v1.18.1-0.20201222143428-b9fdee076426 h1:hgNSbIO7KUJ9jHSEHwM5D2qii5t/5f2yfxZepJFYm18=
+github.com/containers/buildah v1.18.1-0.20201222143428-b9fdee076426/go.mod h1:AM7JcGaUtTJgR6fZL2zBg5PCSCSDiX/sNdMSyrkoJ10=
+github.com/containers/common v0.31.1/go.mod h1:Fehe82hQfJQvDspnRrV9rcdAWG3IalNHEt0F6QWNBHQ=
+github.com/containers/common v0.33.0 h1:7Z6aAQ2s2iniEXd/IoGgc0ukmgmzAE8Oa929t6huVB8=
+github.com/containers/common v0.33.0/go.mod h1:mjDo/NKeweL/onaspLhZ38WnHXaYmrELHclIdvSnYpY=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
-github.com/containers/image/v5 v5.8.1/go.mod h1:blOEFd/iFdeyh891ByhCVUc+xAcaI3gBegXECwz9UbQ=
github.com/containers/image/v5 v5.9.0 h1:dRmUtcluQcmasNo3DpnRoZjfU0rOu1qZeL6wlDJr10Q=
github.com/containers/image/v5 v5.9.0/go.mod h1:blOEFd/iFdeyh891ByhCVUc+xAcaI3gBegXECwz9UbQ=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
@@ -117,11 +112,9 @@ github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQ
github.com/containers/psgo v1.5.2 h1:3aoozst/GIwsrr/5jnFy3FrJay98uujPCu9lTuSZ/Cw=
github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
github.com/containers/storage v1.23.7/go.mod h1:cUT2zHjtx+WlVri30obWmM2gpqpi8jfPsmIzP1TVpEI=
-github.com/containers/storage v1.24.1/go.mod h1:0xJL06Dmd+ZYXIUdnBUPN0JnhHGgwMkLvnnAonJfWJU=
-github.com/containers/storage v1.24.3 h1:8UB4S62l4hrU6Yw3dbsLCJtLg7Ofo39IN2HdckBIX4E=
github.com/containers/storage v1.24.3/go.mod h1:0xJL06Dmd+ZYXIUdnBUPN0JnhHGgwMkLvnnAonJfWJU=
-github.com/containers/storage v1.24.4 h1:QJn/C/4eNbYNpxYdnIn1u4lElIB7V9IesRraLf68JjY=
-github.com/containers/storage v1.24.4/go.mod h1:Y793GKrV3RVM1Jt4QejXtCJHGUPLrDvQ9LAbCyJ9OKs=
+github.com/containers/storage v1.24.5 h1:BusfdU0rCS2/Daa/DPw+0iLfGRlYA7UVF7D0el3N7Vk=
+github.com/containers/storage v1.24.5/go.mod h1:YC+2pY8SkfEAcZkwycxYbpK8EiRbx5soPPwz9dxe4IQ=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
@@ -264,10 +257,9 @@ github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmI
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.3 h1:twObb+9XcuH5B9V1TBCvvvZoO6iEdILi2a76PYn5rJI=
-github.com/google/uuid v1.1.3/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.4 h1:0ecGp3skIrHWPNGPJDaBIghfA6Sp7Ruo2Io8eLKzWm0=
+github.com/google/uuid v1.1.4/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
@@ -335,10 +327,9 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.11.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU=
-github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.5 h1:xNCE0uE6yvTPRS+0wGNMHPo3NIpwnk6aluQZ6R6kRcc=
+github.com/klauspost/compress v1.11.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -719,7 +710,6 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637 h1:O5hKNaGxIT4A8OTMnuh6UpmBdI3SAPxlZ3g0olDrJVM=
golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3 h1:kzM6+9dur93BcC2kVlYl34cHU+TYZLanmpSJHVMmL64=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/libpod/container_api.go b/libpod/container_api.go
index c3e1a23d2..87ff764e3 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -703,6 +703,16 @@ type ContainerCheckpointOptions struct {
// important to be able to restore a container multiple
// times with '--import --name'.
IgnoreStaticMAC bool
+ // IgnoreVolumes tells the API to not export or not to import
+ // the content of volumes associated with the container
+ IgnoreVolumes bool
+ // Pre Checkpoint container and leave container running
+ PreCheckPoint bool
+ // Dump container with Pre Checkpoint images
+ WithPrevious bool
+ // ImportPrevious tells the API to restore container with two
+ // images. One is TargetFile, the other is ImportPrevious.
+ ImportPrevious string
}
// Checkpoint checkpoints a container
@@ -715,6 +725,12 @@ func (c *Container) Checkpoint(ctx context.Context, options ContainerCheckpointO
}
}
+ if options.WithPrevious {
+ if err := c.canWithPrevious(); err != nil {
+ return err
+ }
+ }
+
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index fce26acb0..5aee847e1 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -8,7 +8,6 @@ import (
"strconv"
"time"
- "github.com/containers/common/pkg/capabilities"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/storage/pkg/stringid"
@@ -973,20 +972,12 @@ func (c *Container) removeAllExecSessions() error {
// Make an ExecOptions struct to start the OCI runtime and prepare its exec
// bundle.
func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) {
- // TODO: check logic here - should we set Privileged if the container is
- // privileged?
- var capList []string
- if session.Config.Privileged || c.config.Privileged {
- capList = capabilities.AllCapabilities()
- }
-
if err := c.createExecBundle(session.ID()); err != nil {
return nil, err
}
opts := new(ExecOptions)
opts.Cmd = session.Config.Command
- opts.CapAdd = capList
opts.Env = session.Config.Environment
opts.Terminal = session.Config.Terminal
opts.Cwd = session.Config.WorkDir
@@ -995,6 +986,7 @@ func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) {
opts.DetachKeys = session.Config.DetachKeys
opts.ExitCommand = session.Config.ExitCommand
opts.ExitCommandDelay = session.Config.ExitCommandDelay
+ opts.Privileged = session.Config.Privileged
return opts, nil
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 540230c26..c7548e0e5 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -134,6 +134,11 @@ func (c *Container) CheckpointPath() string {
return filepath.Join(c.bundlePath(), "checkpoint")
}
+// PreCheckpointPath returns the path to the directory containing the pre-checkpoint-images
+func (c *Container) PreCheckPointPath() string {
+ return filepath.Join(c.bundlePath(), "pre-checkpoint")
+}
+
// AttachSocketPath retrieves the path of the container's attach socket
func (c *Container) AttachSocketPath() (string, error) {
return c.ociRuntime.AttachSocketPath(c)
@@ -2023,6 +2028,12 @@ func (c *Container) checkReadyForRemoval() error {
return nil
}
+// canWithPrevious return the stat of the preCheckPoint dir
+func (c *Container) canWithPrevious() error {
+ _, err := os.Stat(c.PreCheckPointPath())
+ return err
+}
+
// writeJSONFile marshalls and writes the given data to a JSON file
// in the bundle path
func (c *Container) writeJSONFile(v interface{}, file string) error {
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index cefe12209..705086bda 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -529,6 +529,13 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
+ availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps()
+ if err != nil {
+ return nil, err
+ }
+ g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs)
+ g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs)
+
// Hostname handling:
// If we have a UTS namespace, set Hostname in the OCI spec.
// Set the HOSTNAME environment variable unless explicitly overridden by
@@ -536,6 +543,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
// set it to the host's hostname instead.
hostname := c.Hostname()
foundUTS := false
+
for _, i := range c.config.Spec.Linux.Namespaces {
if i.Type == spec.UTSNamespace && i.Path == "" {
foundUTS = true
@@ -790,11 +798,11 @@ func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr
return nil
}
-func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
- if (len(c.config.NamedVolumes) > 0) || (len(c.Dependencies()) > 0) {
- return errors.Errorf("Cannot export checkpoints of containers with named volumes or dependencies")
+func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
+ if len(c.Dependencies()) > 0 {
+ return errors.Errorf("Cannot export checkpoints of containers with dependencies")
}
- logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), dest)
+ logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), options.TargetFile)
includeFiles := []string{
"checkpoint",
@@ -804,10 +812,13 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
"spec.dump",
"network.status"}
+ if options.PreCheckPoint {
+ includeFiles[0] = "pre-checkpoint"
+ }
// Get root file-system changes included in the checkpoint archive
rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar")
deleteFilesList := filepath.Join(c.bundlePath(), "deleted.files")
- if !ignoreRootfs {
+ if !options.IgnoreRootfs {
// To correctly track deleted files, let's go through the output of 'podman diff'
tarFiles, err := c.runtime.GetDiff("", c.ID())
if err != nil {
@@ -870,6 +881,47 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
}
}
+ // Folder containing archived volumes that will be included in the export
+ expVolDir := filepath.Join(c.bundlePath(), "volumes")
+
+ // Create an archive for each volume associated with the container
+ if !options.IgnoreVolumes {
+ if err := os.MkdirAll(expVolDir, 0700); err != nil {
+ return errors.Wrapf(err, "error creating volumes export directory %q", expVolDir)
+ }
+
+ for _, v := range c.config.NamedVolumes {
+ volumeTarFilePath := filepath.Join("volumes", v.Name+".tar")
+ volumeTarFileFullPath := filepath.Join(c.bundlePath(), volumeTarFilePath)
+
+ volumeTarFile, err := os.Create(volumeTarFileFullPath)
+ if err != nil {
+ return errors.Wrapf(err, "error creating %q", volumeTarFileFullPath)
+ }
+
+ volume, err := c.runtime.GetVolume(v.Name)
+ if err != nil {
+ return err
+ }
+
+ input, err := archive.TarWithOptions(volume.MountPoint(), &archive.TarOptions{
+ Compression: archive.Uncompressed,
+ IncludeSourceDir: true,
+ })
+ if err != nil {
+ return errors.Wrapf(err, "error reading volume directory %q", v.Dest)
+ }
+
+ _, err = io.Copy(volumeTarFile, input)
+ if err != nil {
+ return err
+ }
+ volumeTarFile.Close()
+
+ includeFiles = append(includeFiles, volumeTarFilePath)
+ }
+ }
+
input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{
Compression: archive.Gzip,
IncludeSourceDir: true,
@@ -880,13 +932,13 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
return errors.Wrapf(err, "error reading checkpoint directory %q", c.ID())
}
- outFile, err := os.Create(dest)
+ outFile, err := os.Create(options.TargetFile)
if err != nil {
- return errors.Wrapf(err, "error creating checkpoint export file %q", dest)
+ return errors.Wrapf(err, "error creating checkpoint export file %q", options.TargetFile)
}
defer outFile.Close()
- if err := os.Chmod(dest, 0600); err != nil {
+ if err := os.Chmod(options.TargetFile, 0600); err != nil {
return err
}
@@ -898,6 +950,10 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
os.Remove(rootfsDiffPath)
os.Remove(deleteFilesList)
+ if !options.IgnoreVolumes {
+ os.RemoveAll(expVolDir)
+ }
+
return nil
}
@@ -962,15 +1018,24 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
defer c.newContainerEvent(events.Checkpoint)
+ // There is a bug from criu: https://github.com/checkpoint-restore/criu/issues/116
+ // We have to change the symbolic link from absolute path to relative path
+ if options.WithPrevious {
+ os.Remove(path.Join(c.CheckpointPath(), "parent"))
+ if err := os.Symlink("../pre-checkpoint", path.Join(c.CheckpointPath(), "parent")); err != nil {
+ return err
+ }
+ }
+
if options.TargetFile != "" {
- if err = c.exportCheckpoint(options.TargetFile, options.IgnoreRootfs); err != nil {
+ if err = c.exportCheckpoint(options); err != nil {
return err
}
}
logrus.Debugf("Checkpointed container %s", c.ID())
- if !options.KeepRunning {
+ if !options.KeepRunning && !options.PreCheckPoint {
c.state.State = define.ContainerStateStopped
// Cleanup Storage and Network
@@ -979,7 +1044,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
}
}
- if !options.Keep {
+ if !options.Keep && !options.PreCheckPoint {
cleanup := []string{
"dump.log",
"stats-dump",
@@ -1027,6 +1092,21 @@ func (c *Container) importCheckpoint(input string) error {
return nil
}
+func (c *Container) importPreCheckpoint(input string) error {
+ archiveFile, err := os.Open(input)
+ if err != nil {
+ return errors.Wrap(err, "failed to open pre-checkpoint archive for import")
+ }
+
+ defer archiveFile.Close()
+
+ err = archive.Untar(archiveFile, c.bundlePath(), nil)
+ if err != nil {
+ return errors.Wrapf(err, "Unpacking of pre-checkpoint archive %s failed", input)
+ }
+ return nil
+}
+
func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (retErr error) {
if err := c.checkpointRestoreSupported(); err != nil {
return err
@@ -1036,6 +1116,12 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID())
}
+ if options.ImportPrevious != "" {
+ if err := c.importPreCheckpoint(options.ImportPrevious); err != nil {
+ return err
+ }
+ }
+
if options.TargetFile != "" {
if err := c.importCheckpoint(options.TargetFile); err != nil {
return err
@@ -1193,6 +1279,30 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return err
}
+ // When restoring from an imported archive, allow restoring the content of volumes.
+ // Volumes are created in setupContainer()
+ if options.TargetFile != "" && !options.IgnoreVolumes {
+ for _, v := range c.config.NamedVolumes {
+ volumeFilePath := filepath.Join(c.bundlePath(), "volumes", v.Name+".tar")
+
+ volumeFile, err := os.Open(volumeFilePath)
+ if err != nil {
+ return errors.Wrapf(err, "Failed to open volume file %s", volumeFilePath)
+ }
+ defer volumeFile.Close()
+
+ volume, err := c.runtime.GetVolume(v.Name)
+ if err != nil {
+ return errors.Wrapf(err, "Failed to retrieve volume %s", v.Name)
+ }
+
+ mountPoint := volume.MountPoint()
+ if err := archive.UntarUncompressed(volumeFile, mountPoint, nil); err != nil {
+ return errors.Wrapf(err, "Failed to extract volume %s to %s", volumeFilePath, mountPoint)
+ }
+ }
+ }
+
// Before actually restarting the container, apply the root file-system changes
if !options.IgnoreRootfs {
rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar")
@@ -1245,6 +1355,10 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if err != nil {
logrus.Debugf("Non-fatal: removal of checkpoint directory (%s) failed: %v", c.CheckpointPath(), err)
}
+ err = os.RemoveAll(c.PreCheckPointPath())
+ if err != nil {
+ logrus.Debugf("Non-fatal: removal of pre-checkpoint directory (%s) failed: %v", c.PreCheckPointPath(), err)
+ }
cleanup := [...]string{"restore.log", "dump.log", "stats-dump", "stats-restore", "network.status", "rootfs-diff.tar", "deleted.files"}
for _, del := range cleanup {
file := filepath.Join(c.bundlePath(), del)
diff --git a/libpod/container_log.go b/libpod/container_log.go
index e58503bd3..f16e08353 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -82,7 +82,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
if nll.Partial() {
partial += nll.Msg
continue
- } else if !nll.Partial() && len(partial) > 1 {
+ } else if !nll.Partial() && len(partial) > 0 {
nll.Msg = partial + nll.Msg
partial = ""
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index be6867399..addf1814c 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -685,7 +685,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error {
return errors.Wrapf(err, "failed to generate random netns name")
}
- nsPath := fmt.Sprintf("/var/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
+ nsPath := fmt.Sprintf("/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil {
return err
diff --git a/libpod/oci.go b/libpod/oci.go
index 157c42c38..6948e6425 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -151,8 +151,6 @@ type OCIRuntime interface {
type ExecOptions struct {
// Cmd is the command to execute.
Cmd []string
- // CapAdd is a set of capabilities to add to the executed command.
- CapAdd []string
// Env is a set of environment variables to add to the container.
Env map[string]string
// Terminal is whether to create a new TTY for the exec session.
@@ -181,6 +179,8 @@ type ExecOptions struct {
// ExitCommandDelay is a delay (in seconds) between the exec session
// exiting, and the exit command being invoked.
ExitCommandDelay uint
+ // Privileged indicates the execed process will be launched in Privileged mode
+ Privileged bool
}
// HTTPAttachStreams informs the HTTPAttach endpoint which of the container's
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index fbc95510e..4556eba94 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -28,6 +28,15 @@ const (
AttachPipeStderr = 3
)
+func openUnixSocket(path string) (*net.UnixConn, error) {
+ fd, err := unix.Open(path, unix.O_PATH, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer unix.Close(fd)
+ return net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: fmt.Sprintf("/proc/self/fd/%d", fd), Net: "unixpacket"})
+}
+
// Attach to the given container
// Does not check if state is appropriate
// started is only required if startContainer is true
@@ -52,11 +61,10 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
if err != nil {
return err
}
- socketPath := buildSocketPath(attachSock)
- conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ conn, err := openUnixSocket(attachSock)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
}
defer func() {
if err := conn.Close(); err != nil {
@@ -124,7 +132,6 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se
if err != nil {
return err
}
- socketPath := buildSocketPath(sockPath)
// 2: read from attachFd that the parent process has set up the console socket
if _, err := readConmonPipeData(attachFd, ""); err != nil {
@@ -132,9 +139,9 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se
}
// 2: then attach
- conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ conn, err := openUnixSocket(sockPath)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath)
}
defer func() {
if err := conn.Close(); err != nil {
@@ -182,16 +189,6 @@ func registerResizeFunc(resize <-chan remotecommand.TerminalSize, bundlePath str
})
}
-func buildSocketPath(socketPath string) string {
- maxUnixLength := unixPathLength()
- if maxUnixLength < len(socketPath) {
- socketPath = socketPath[0:maxUnixLength]
- }
-
- logrus.Debug("connecting to socket ", socketPath)
- return socketPath
-}
-
func setupStdioChannels(streams *define.AttachStreams, conn *net.UnixConn, detachKeys []byte) (chan error, chan error) {
receiveStdoutError := make(chan error)
go func() {
diff --git a/libpod/oci_attach_linux_cgo.go b/libpod/oci_attach_linux_cgo.go
deleted file mode 100644
index d81243360..000000000
--- a/libpod/oci_attach_linux_cgo.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//+build linux,cgo
-
-package libpod
-
-//#include <sys/un.h>
-// extern int unix_path_length(){struct sockaddr_un addr; return sizeof(addr.sun_path) - 1;}
-import "C"
-
-func unixPathLength() int {
- return int(C.unix_path_length())
-}
diff --git a/libpod/oci_attach_linux_nocgo.go b/libpod/oci_attach_linux_nocgo.go
deleted file mode 100644
index a514a555d..000000000
--- a/libpod/oci_attach_linux_nocgo.go
+++ /dev/null
@@ -1,7 +0,0 @@
-//+build linux,!cgo
-
-package libpod
-
-func unixPathLength() int {
- return 107
-}
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 4546acefb..dc5dd03df 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -2,7 +2,6 @@ package libpod
import (
"fmt"
- "net"
"net/http"
"os"
"os/exec"
@@ -398,10 +397,6 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
args = append(args, formatRuntimeOpts("--preserve-fds", fmt.Sprintf("%d", options.PreserveFDs))...)
}
- for _, capability := range options.CapAdd {
- args = append(args, formatRuntimeOpts("--cap", capability)...)
- }
-
if options.Terminal {
args = append(args, "-t")
}
@@ -516,7 +511,6 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
if err != nil {
return err
}
- socketPath := buildSocketPath(sockPath)
// 2: read from attachFd that the parent process has set up the console socket
if _, err := readConmonPipeData(pipes.attachPipe, ""); err != nil {
@@ -524,9 +518,9 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
}
// 2: then attach
- conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ conn, err := openUnixSocket(sockPath)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath)
}
defer func() {
if err := conn.Close(); err != nil {
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index e7cb5a802..70896cda4 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -22,6 +22,7 @@ import (
"text/template"
"time"
+ "github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/config"
conmonConfig "github.com/containers/conmon/runner/config"
"github.com/containers/podman/v2/libpod/define"
@@ -528,13 +529,12 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
if err != nil {
return err
}
- socketPath := buildSocketPath(attachSock)
var conn *net.UnixConn
if streamAttach {
- newConn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ newConn, err := openUnixSocket(attachSock)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
}
conn = newConn
defer func() {
@@ -543,7 +543,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
}
}()
- logrus.Debugf("Successfully connected to container %s attach socket %s", ctr.ID(), socketPath)
+ logrus.Debugf("Successfully connected to container %s attach socket %s", ctr.ID(), attachSock)
}
detachString := ctr.runtime.config.Engine.DetachKeys
@@ -768,10 +768,14 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
}
// imagePath is used by CRIU to store the actual checkpoint files
imagePath := ctr.CheckpointPath()
+ if options.PreCheckPoint {
+ imagePath = ctr.PreCheckPointPath()
+ }
// workPath will be used to store dump.log and stats-dump
workPath := ctr.bundlePath()
logrus.Debugf("Writing checkpoint to %s", imagePath)
logrus.Debugf("Writing checkpoint logs to %s", workPath)
+ logrus.Debugf("Pre-dump the container %t", options.PreCheckPoint)
args := []string{}
args = append(args, r.runtimeFlags...)
args = append(args, "checkpoint")
@@ -785,6 +789,15 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
if options.TCPEstablished {
args = append(args, "--tcp-established")
}
+ if !options.PreCheckPoint && options.KeepRunning {
+ args = append(args, "--leave-running")
+ }
+ if options.PreCheckPoint {
+ args = append(args, "--pre-dump")
+ }
+ if !options.PreCheckPoint && options.WithPrevious {
+ args = append(args, "--parent-path", ctr.PreCheckPointPath())
+ }
runtimeDir, err := util.GetRuntimeDir()
if err != nil {
return err
@@ -793,6 +806,7 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
}
args = append(args, ctr.ID())
+ logrus.Debugf("the args to checkpoint: %s %s", r.path, strings.Join(args, " "))
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...)
}
@@ -1201,13 +1215,7 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
}
pspec.SelinuxLabel = c.config.ProcessLabel
pspec.Args = options.Cmd
- for _, cap := range options.CapAdd {
- pspec.Capabilities.Bounding = append(pspec.Capabilities.Bounding, cap)
- pspec.Capabilities.Effective = append(pspec.Capabilities.Effective, cap)
- pspec.Capabilities.Inheritable = append(pspec.Capabilities.Inheritable, cap)
- pspec.Capabilities.Permitted = append(pspec.Capabilities.Permitted, cap)
- pspec.Capabilities.Ambient = append(pspec.Capabilities.Ambient, cap)
- }
+
// We need to default this to false else it will inherit terminal as true
// from the container.
pspec.Terminal = false
@@ -1263,6 +1271,31 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
pspec.User = processUser
}
+ ctrSpec, err := c.specFromState()
+ if err != nil {
+ return nil, err
+ }
+
+ allCaps := capabilities.AllCapabilities()
+ if options.Privileged {
+ pspec.Capabilities.Bounding = allCaps
+ } else {
+ pspec.Capabilities.Bounding = ctrSpec.Process.Capabilities.Bounding
+ }
+ if execUser.Uid == 0 {
+ pspec.Capabilities.Effective = pspec.Capabilities.Bounding
+ pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding
+ pspec.Capabilities.Permitted = pspec.Capabilities.Bounding
+ pspec.Capabilities.Ambient = pspec.Capabilities.Bounding
+ } else {
+ if user == c.config.User {
+ pspec.Capabilities.Effective = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Inheritable = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Permitted = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Ambient = ctrSpec.Process.Capabilities.Effective
+ }
+ }
+
hasHomeSet := false
for _, s := range pspec.Env {
if strings.HasPrefix(s, "HOME=") {
@@ -1288,7 +1321,12 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
// configureConmonEnv gets the environment values to add to conmon's exec struct
// TODO this may want to be less hardcoded/more configurable in the future
func (r *ConmonOCIRuntime) configureConmonEnv(ctr *Container, runtimeDir string) ([]string, []*os.File) {
- env := make([]string, 0, 6)
+ var env []string
+ for _, e := range os.Environ() {
+ if strings.HasPrefix(e, "LC_") {
+ env = append(env, e)
+ }
+ }
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
env = append(env, fmt.Sprintf("_CONTAINERS_USERNS_CONFIGURED=%s", os.Getenv("_CONTAINERS_USERNS_CONFIGURED")))
env = append(env, fmt.Sprintf("_CONTAINERS_ROOTLESS_UID=%s", os.Getenv("_CONTAINERS_ROOTLESS_UID")))
diff --git a/libpod/options.go b/libpod/options.go
index 8100eee62..ef7db3235 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -306,7 +306,7 @@ func WithDefaultMountsFile(mountsFile string) RuntimeOption {
// WithTmpDir sets the directory that temporary runtime files which are not
// expected to survive across reboots will be stored.
-// This should be located on a tmpfs mount (/tmp or /var/run for example).
+// This should be located on a tmpfs mount (/tmp or /run for example).
func WithTmpDir(dir string) RuntimeOption {
return func(rt *Runtime) error {
if rt.valid {
diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go
index b3d26b8f4..7bba38475 100644
--- a/pkg/api/handlers/compat/containers_prune.go
+++ b/pkg/api/handlers/compat/containers_prune.go
@@ -1,9 +1,11 @@
package compat
import (
+ "bytes"
"net/http"
"github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/domain/filters"
@@ -32,33 +34,45 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) {
filterFuncs = append(filterFuncs, generatedFunc)
}
+ report, err := PruneContainersHelper(r, filterFuncs)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+
// Libpod response differs
if utils.IsLibpodRequest(r) {
- report, err := PruneContainersHelper(w, r, filterFuncs)
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
-
utils.WriteResponse(w, http.StatusOK, report)
return
}
- report, err := runtime.PruneContainers(filterFuncs)
- if err != nil {
- utils.InternalServerError(w, err)
+ var payload handlers.ContainersPruneReport
+ var errorMsg bytes.Buffer
+ for _, pr := range report {
+ if pr.Err != nil {
+ // Docker stops on first error vs. libpod which keeps going. Given API constraints, concatenate all errors
+ // and return that string.
+ errorMsg.WriteString(pr.Err.Error())
+ errorMsg.WriteString("; ")
+ continue
+ }
+ payload.ContainersDeleted = append(payload.ContainersDeleted, pr.Id)
+ payload.SpaceReclaimed += pr.Size
+ }
+ if errorMsg.Len() > 0 {
+ utils.InternalServerError(w, errors.New(errorMsg.String()))
return
}
- utils.WriteResponse(w, http.StatusOK, report)
+
+ utils.WriteResponse(w, http.StatusOK, payload)
}
-func PruneContainersHelper(w http.ResponseWriter, r *http.Request, filterFuncs []libpod.ContainerFilter) (
- []*reports.PruneReport, error) {
+func PruneContainersHelper(r *http.Request, filterFuncs []libpod.ContainerFilter) ([]*reports.PruneReport, error) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- reports, err := runtime.PruneContainers(filterFuncs)
+
+ report, err := runtime.PruneContainers(filterFuncs)
if err != nil {
- utils.InternalServerError(w, err)
return nil, err
}
- return reports, nil
+ return report, nil
}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 9d7503aba..0ae0f3bcf 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -18,7 +18,6 @@ import (
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/auth"
"github.com/containers/podman/v2/pkg/domain/entities"
- "github.com/docker/docker/api/types"
"github.com/gorilla/schema"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
@@ -74,52 +73,6 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, rdr)
}
-func PruneImages(w http.ResponseWriter, r *http.Request) {
- var (
- filters []string
- )
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
-
- query := struct {
- All bool
- Filters map[string][]string `schema:"filters"`
- }{
- // This is where you can override the golang default value for one of fields
- }
-
- if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
- return
- }
-
- idr := []types.ImageDeleteResponseItem{}
- for k, v := range query.Filters {
- for _, val := range v {
- filters = append(filters, fmt.Sprintf("%s=%s", k, val))
- }
- }
- imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters)
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- reclaimedSpace := uint64(0)
- for _, p := range imagePruneReports {
- idr = append(idr, types.ImageDeleteResponseItem{
- Deleted: p.Id,
- })
- reclaimedSpace = reclaimedSpace + p.Size
- }
-
- // FIXME/TODO to do this exactly correct, pruneimages needs to return idrs and space-reclaimed, then we are golden
- ipr := types.ImagesPruneReport{
- ImagesDeleted: idr,
- SpaceReclaimed: reclaimedSpace,
- }
- utils.WriteResponse(w, http.StatusOK, handlers.ImagesPruneReport{ImagesPruneReport: ipr})
-}
-
func CommitContainer(w http.ResponseWriter, r *http.Request) {
var (
destImage string
diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go
new file mode 100644
index 000000000..c7e84804b
--- /dev/null
+++ b/pkg/api/handlers/compat/images_prune.go
@@ -0,0 +1,75 @@
+package compat
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+
+ "github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/pkg/api/handlers"
+ "github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/docker/docker/api/types"
+ "github.com/gorilla/schema"
+ "github.com/pkg/errors"
+)
+
+func PruneImages(w http.ResponseWriter, r *http.Request) {
+ var (
+ filters []string
+ )
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ query := struct {
+ All bool
+ Filters map[string][]string `schema:"filters"`
+ }{
+ // This is where you can override the golang default value for one of fields
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ for k, v := range query.Filters {
+ for _, val := range v {
+ filters = append(filters, fmt.Sprintf("%s=%s", k, val))
+ }
+ }
+ imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ idr := make([]types.ImageDeleteResponseItem, len(imagePruneReports))
+ var reclaimedSpace uint64
+ var errorMsg bytes.Buffer
+ for _, p := range imagePruneReports {
+ if p.Err != nil {
+ // Docker stops on first error vs. libpod which keeps going. Given API constraints, concatenate all errors
+ // and return that string.
+ errorMsg.WriteString(p.Err.Error())
+ errorMsg.WriteString("; ")
+ continue
+ }
+
+ idr = append(idr, types.ImageDeleteResponseItem{
+ Deleted: p.Id,
+ })
+ reclaimedSpace = reclaimedSpace + p.Size
+ }
+ if errorMsg.Len() > 0 {
+ utils.InternalServerError(w, errors.New(errorMsg.String()))
+ return
+ }
+
+ payload := handlers.ImagesPruneReport{
+ ImagesPruneReport: types.ImagesPruneReport{
+ ImagesDeleted: idr,
+ SpaceReclaimed: reclaimedSpace,
+ },
+ }
+ utils.WriteResponse(w, http.StatusOK, payload)
+}
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index 1188d8f84..4903bbad4 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -1,6 +1,7 @@
package compat
import (
+ "bytes"
"encoding/json"
"net/http"
"net/url"
@@ -8,6 +9,7 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/domain/infra/abi/parse"
@@ -268,17 +270,29 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
+
+ var errorMsg bytes.Buffer
+ var reclaimedSpace uint64
prunedIds := make([]string, 0, len(pruned))
for _, v := range pruned {
- // XXX: This drops any pruning per-volume error messages on the floor
+ if v.Err != nil {
+ errorMsg.WriteString(v.Err.Error())
+ errorMsg.WriteString("; ")
+ continue
+ }
prunedIds = append(prunedIds, v.Id)
+ reclaimedSpace += v.Size
}
- pruneResponse := docker_api_types.VolumesPruneReport{
- VolumesDeleted: prunedIds,
- // TODO: We don't have any insight into how much space was reclaimed
- // from `PruneVolumes()` but it's not nullable
- SpaceReclaimed: 0,
+ if errorMsg.Len() > 0 {
+ utils.InternalServerError(w, errors.New(errorMsg.String()))
+ return
}
- utils.WriteResponse(w, http.StatusOK, pruneResponse)
+ payload := handlers.VolumesPruneReport{
+ VolumesPruneReport: docker_api_types.VolumesPruneReport{
+ VolumesDeleted: prunedIds,
+ SpaceReclaimed: reclaimedSpace,
+ },
+ }
+ utils.WriteResponse(w, http.StatusOK, payload)
}
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 14eb44831..6b07b1cc5 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -275,6 +275,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
Import bool `schema:"import"`
Name string `schema:"name"`
IgnoreRootFS bool `schema:"ignoreRootFS"`
+ IgnoreVolumes bool `schema:"ignoreVolumes"`
IgnoreStaticIP bool `schema:"ignoreStaticIP"`
IgnoreStaticMAC bool `schema:"ignoreStaticMAC"`
}{
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 5422411cf..2409d3a20 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -43,6 +43,7 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
}
func Pods(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
Filters map[string][]string `schema:"filters"`
@@ -55,7 +56,11 @@ func Pods(w http.ResponseWriter, r *http.Request) {
return
}
- pods, err := utils.GetPods(w, r)
+ containerEngine := abi.ContainerEngine{Libpod: runtime}
+ podPSOptions := entities.PodPSOptions{
+ Filters: query.Filters,
+ }
+ pods, err := containerEngine.PodPs(r.Context(), podPSOptions)
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
@@ -235,7 +240,7 @@ func PodRestart(w http.ResponseWriter, r *http.Request) {
}
func PodPrune(w http.ResponseWriter, r *http.Request) {
- reports, err := PodPruneHelper(w, r)
+ reports, err := PodPruneHelper(r)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -243,7 +248,7 @@ func PodPrune(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, reports)
}
-func PodPruneHelper(w http.ResponseWriter, r *http.Request) ([]*entities.PodPruneReport, error) {
+func PodPruneHelper(r *http.Request) ([]*entities.PodPruneReport, error) {
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
)
diff --git a/pkg/api/handlers/libpod/system.go b/pkg/api/handlers/libpod/system.go
index 130e563ae..c48c186ed 100644
--- a/pkg/api/handlers/libpod/system.go
+++ b/pkg/api/handlers/libpod/system.go
@@ -30,7 +30,7 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) {
return
}
- podPruneReport, err := PodPruneHelper(w, r)
+ podPruneReport, err := PodPruneHelper(r)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -38,7 +38,7 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) {
systemPruneReport.PodPruneReport = podPruneReport
// We could parallelize this, should we?
- containerPruneReports, err := compat.PruneContainersHelper(w, r, nil)
+ containerPruneReports, err := compat.PruneContainersHelper(r, nil)
if err != nil {
utils.InternalServerError(w, err)
return
diff --git a/pkg/api/handlers/utils/pods.go b/pkg/api/handlers/utils/pods.go
deleted file mode 100644
index 0fe3a308b..000000000
--- a/pkg/api/handlers/utils/pods.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package utils
-
-import (
- "net/http"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/pkg/domain/entities"
- dfilters "github.com/containers/podman/v2/pkg/domain/filters"
- "github.com/gorilla/schema"
-)
-
-func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport, error) {
- var (
- pods []*libpod.Pod
- )
- runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
-
- query := struct {
- All bool
- Filters map[string][]string `schema:"filters"`
- Digests bool
- }{}
-
- if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- return nil, err
- }
- if _, found := r.URL.Query()["digests"]; found && query.Digests {
- UnSupportedParameter("digests")
- }
-
- filters := make([]libpod.PodFilter, 0, len(query.Filters))
- for k, v := range query.Filters {
- f, err := dfilters.GeneratePodFilterFunc(k, v)
- if err != nil {
- return nil, err
- }
- filters = append(filters, f)
- }
- pods, err := runtime.Pods(filters...)
- if err != nil {
- return nil, err
- }
-
- if len(pods) == 0 {
- return []*entities.ListPodsReport{}, nil
- }
-
- lps := make([]*entities.ListPodsReport, 0, len(pods))
- for _, pod := range pods {
- status, err := pod.GetPodStatus()
- if err != nil {
- return nil, err
- }
- ctrs, err := pod.AllContainers()
- if err != nil {
- return nil, err
- }
- infraID, err := pod.InfraContainerID()
- if err != nil {
- return nil, err
- }
- lp := entities.ListPodsReport{
- Cgroup: pod.CgroupParent(),
- Created: pod.CreatedTime(),
- Id: pod.ID(),
- Name: pod.Name(),
- Namespace: pod.Namespace(),
- Status: status,
- InfraId: infraID,
- Labels: pod.Labels(),
- }
- for _, ctr := range ctrs {
- state, err := ctr.State()
- if err != nil {
- return nil, err
- }
- lp.Containers = append(lp.Containers, &entities.ListPodContainer{
- Id: ctr.ID(),
- Names: ctr.Name(),
- Status: state.String(),
- })
- }
- lps = append(lps, &lp)
- }
- return lps, nil
-}
diff --git a/pkg/api/server/docs.go b/pkg/api/server/docs.go
index 1aaf31117..a99fefd7b 100644
--- a/pkg/api/server/docs.go
+++ b/pkg/api/server/docs.go
@@ -13,7 +13,7 @@
// You can then use cURL on the socket using requests documented below.
//
// NOTE: if you install the package podman-docker, it will create a symbolic
-// link for /var/run/docker.sock to /run/podman/podman.sock
+// link for /run/docker.sock to /run/podman/podman.sock
//
// See podman-service(1) for more information.
//
diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go
index e6c85d244..967d7da76 100644
--- a/pkg/api/server/register_networks.go
+++ b/pkg/api/server/register_networks.go
@@ -9,6 +9,19 @@ import (
)
func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
+ // swagger:operation POST /networks/prune compat compatPruneNetwork
+ // ---
+ // tags:
+ // - networks (compat)
+ // Summary: Delete unused networks
+ // description: Not supported
+ // produces:
+ // - application/json
+ // responses:
+ // 404:
+ // $ref: "#/responses/NoSuchNetwork"
+ r.HandleFunc(VersionedPath("/networks/prune"), compat.UnsupportedHandler).Methods(http.MethodPost)
+ r.HandleFunc("/networks/prune", compat.UnsupportedHandler).Methods(http.MethodPost)
// swagger:operation DELETE /networks/{name} compat compatRemoveNetwork
// ---
// tags:
diff --git a/pkg/checkpoint/checkpoint_restore.go b/pkg/checkpoint/checkpoint_restore.go
index 9de04266f..f6cd3b38f 100644
--- a/pkg/checkpoint/checkpoint_restore.go
+++ b/pkg/checkpoint/checkpoint_restore.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/image"
+ "github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/errorhandling"
"github.com/containers/podman/v2/pkg/util"
"github.com/containers/storage/pkg/archive"
@@ -36,10 +37,10 @@ func crImportFromJSON(filePath string, v interface{}) error {
// CRImportCheckpoint it the function which imports the information
// from checkpoint tarball and re-creates the container from that information
-func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input string, name string) ([]*libpod.Container, error) {
+func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOptions entities.RestoreOptions) ([]*libpod.Container, error) {
// First get the container definition from the
// tarball to a temporary directory
- archiveFile, err := os.Open(input)
+ archiveFile, err := os.Open(restoreOptions.Import)
if err != nil {
return nil, errors.Wrap(err, "failed to open checkpoint archive for import")
}
@@ -53,6 +54,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri
"rootfs-diff.tar",
"network.status",
"deleted.files",
+ "volumes",
},
}
dir, err := ioutil.TempDir("", "checkpoint")
@@ -66,7 +68,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri
}()
err = archive.Untar(archiveFile, dir, options)
if err != nil {
- return nil, errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input)
+ return nil, errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", restoreOptions.Import)
}
// Load spec.dump from temporary directory
@@ -82,17 +84,30 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri
}
// This should not happen as checkpoints with these options are not exported.
- if (len(config.Dependencies) > 0) || (len(config.NamedVolumes) > 0) {
- return nil, errors.Errorf("Cannot import checkpoints of containers with named volumes or dependencies")
+ if len(config.Dependencies) > 0 {
+ return nil, errors.Errorf("Cannot import checkpoints of containers with dependencies")
+ }
+
+ // Volumes included in the checkpoint should not exist
+ if !restoreOptions.IgnoreVolumes {
+ for _, vol := range config.NamedVolumes {
+ exists, err := runtime.HasVolume(vol.Name)
+ if err != nil {
+ return nil, err
+ }
+ if exists {
+ return nil, errors.Errorf("volume with name %s already exists. Use --ignore-volumes to not restore content of volumes", vol.Name)
+ }
+ }
}
ctrID := config.ID
newName := false
// Check if the restored container gets a new name
- if name != "" {
+ if restoreOptions.Name != "" {
config.ID = ""
- config.Name = name
+ config.Name = restoreOptions.Name
newName = true
}
diff --git a/pkg/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go
index ff3b087ed..6709ca48a 100644
--- a/pkg/domain/entities/container_ps.go
+++ b/pkg/domain/entities/container_ps.go
@@ -43,6 +43,8 @@ type ListContainer struct {
// Namespaces the container belongs to. Requires the
// namespace boolean to be true
Namespaces ListContainerNamespaces
+ // The network names assigned to the container
+ Networks []string
// The process id of the container
Pid int
// If the container is part of Pod, the Pod ID. Requires the pod
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 05b9b774e..96687b1de 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -173,10 +173,13 @@ type CheckpointOptions struct {
All bool
Export string
IgnoreRootFS bool
+ IgnoreVolumes bool
Keep bool
Latest bool
LeaveRunning bool
TCPEstablished bool
+ PreCheckPoint bool
+ WithPrevious bool
}
type CheckpointReport struct {
@@ -187,6 +190,7 @@ type CheckpointReport struct {
type RestoreOptions struct {
All bool
IgnoreRootFS bool
+ IgnoreVolumes bool
IgnoreStaticIP bool
IgnoreStaticMAC bool
Import string
@@ -194,6 +198,7 @@ type RestoreOptions struct {
Latest bool
Name string
TCPEstablished bool
+ ImportPrevious string
}
type RestoreReport struct {
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 0b42e1a3f..6883fe6c5 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -40,6 +40,9 @@ type PlayKubePod struct {
Containers []string
// Logs - non-fatal errors and log messages while processing.
Logs []string
+ // ContainerErrors - any errors that occurred while starting containers
+ // in the pod.
+ ContainerErrors []string
}
// PlayKubeReport contains the results of running play kube.
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index 426419833..edb0af15a 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -28,8 +28,10 @@ type ListPodsReport struct {
InfraId string //nolint
Name string
Namespace string
- Status string
- Labels map[string]string
+ // Network names connected to infra container
+ Networks []string
+ Status string
+ Labels map[string]string
}
type ListPodContainer struct {
diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go
index ce6c12b71..09ef6201a 100644
--- a/pkg/domain/filters/containers.go
+++ b/pkg/domain/filters/containers.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/libpod/network"
"github.com/containers/podman/v2/pkg/timetype"
"github.com/containers/podman/v2/pkg/util"
"github.com/pkg/errors"
@@ -233,6 +234,24 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
}
return false
}, nil
+ case "network":
+ return func(c *libpod.Container) bool {
+ networks, _, err := c.Networks()
+ // if err or no networks, quick out
+ if err != nil || len(networks) == 0 {
+ return false
+ }
+ for _, net := range networks {
+ netID := network.GetNetworkID(net)
+ for _, val := range filterValues {
+ // match by network name or id
+ if val == net || val == netID {
+ return true
+ }
+ }
+ }
+ return false
+ }, nil
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go
index 7e6b7f2cc..685c182ba 100644
--- a/pkg/domain/filters/pods.go
+++ b/pkg/domain/filters/pods.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/libpod/network"
"github.com/containers/podman/v2/pkg/util"
"github.com/pkg/errors"
)
@@ -134,6 +135,29 @@ func GeneratePodFilterFunc(filter string, filterValues []string) (
}
return true
}, nil
+ case "network":
+ return func(p *libpod.Pod) bool {
+ infra, err := p.InfraContainer()
+ // no infra, quick out
+ if err != nil {
+ return false
+ }
+ networks, _, err := infra.Networks()
+ // if err or no networks, quick out
+ if err != nil || len(networks) == 0 {
+ return false
+ }
+ for _, net := range networks {
+ netID := network.GetNetworkID(net)
+ for _, val := range filterValues {
+ // match by network name or id
+ if val == net || val == netID {
+ return true
+ }
+ }
+ }
+ return false
+ }, nil
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 9d7c2daea..2c79b6187 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -487,7 +487,10 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
TCPEstablished: options.TCPEstablished,
TargetFile: options.Export,
IgnoreRootfs: options.IgnoreRootFS,
+ IgnoreVolumes: options.IgnoreVolumes,
KeepRunning: options.LeaveRunning,
+ PreCheckPoint: options.PreCheckPoint,
+ WithPrevious: options.WithPrevious,
}
if options.All {
@@ -525,8 +528,10 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
TargetFile: options.Import,
Name: options.Name,
IgnoreRootfs: options.IgnoreRootFS,
+ IgnoreVolumes: options.IgnoreVolumes,
IgnoreStaticIP: options.IgnoreStaticIP,
IgnoreStaticMAC: options.IgnoreStaticMAC,
+ ImportPrevious: options.ImportPrevious,
}
filterFuncs := []libpod.ContainerFilter{
@@ -538,7 +543,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
switch {
case options.Import != "":
- cons, err = checkpoint.CRImportCheckpoint(ctx, ic.Libpod, options.Import, options.Name)
+ cons, err = checkpoint.CRImportCheckpoint(ctx, ic.Libpod, options)
case options.All:
cons, err = ic.Libpod.GetContainers(filterFuncs...)
default:
diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go
index c4b0b7712..2d3b9f36a 100644
--- a/pkg/domain/infra/abi/images_list.go
+++ b/pkg/domain/infra/abi/images_list.go
@@ -44,7 +44,10 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
}
e.Labels, err = img.Labels(ctx)
if err != nil {
- return nil, errors.Wrapf(err, "error retrieving label for image %q: you may need to remove the image to resolve the error", img.ID())
+ // Ignore empty manifest lists.
+ if errors.Cause(err) != libpodImage.ErrImageIsBareList {
+ return nil, errors.Wrapf(err, "error retrieving label for image %q: you may need to remove the image to resolve the error", img.ID())
+ }
}
ctnrs, err := img.Containers()
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index cbc74a2f2..70c7104f1 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/specgen/generate"
@@ -251,21 +252,13 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
if options.Start != types.OptionalBoolFalse {
- //start the containers
+ // Start the containers
podStartErrors, err := pod.Start(ctx)
- if err != nil {
+ if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
return nil, err
}
-
- // Previous versions of playkube started containers individually and then
- // looked for errors. Because we now use the uber-Pod start call, we should
- // iterate the map of possible errors and return one if there is a problem. This
- // keeps the behavior the same
-
- for _, e := range podStartErrors {
- if e != nil {
- return nil, e
- }
+ for id, err := range podStartErrors {
+ playKubePod.ContainerErrors = append(playKubePod.ContainerErrors, errors.Wrapf(err, "error starting container %s", id).Error())
}
}
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index f108b770c..2a8445c9f 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -333,6 +333,17 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
if err != nil {
return nil, err
}
+ networks := []string{}
+ if len(infraID) > 0 {
+ infra, err := p.InfraContainer()
+ if err != nil {
+ return nil, err
+ }
+ networks, _, err = infra.Networks()
+ if err != nil {
+ return nil, err
+ }
+ }
reports = append(reports, &entities.ListPodsReport{
Cgroup: p.CgroupParent(),
Containers: lpcs,
@@ -341,6 +352,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
InfraId: infraID,
Name: p.Name(),
Namespace: p.Namespace(),
+ Networks: networks,
Status: status,
Labels: p.Labels(),
})
diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go
index ed5241632..6817a3abd 100644
--- a/pkg/netns/netns_linux.go
+++ b/pkg/netns/netns_linux.go
@@ -45,7 +45,7 @@ func getNSRunDir() (string, error) {
}
return filepath.Join(rootlessDir, "netns"), nil
}
- return "/var/run/netns", nil
+ return "/run/netns", nil
}
// NewNS creates a new persistent (bind-mounted) network namespace and returns
@@ -80,7 +80,7 @@ func NewNS() (ns.NetNS, error) {
return nil, fmt.Errorf("mount --make-rshared %s failed: %q", nsRunDir, err)
}
- // Recursively remount /var/run/netns on itself. The recursive flag is
+ // Recursively remount /run/netns on itself. The recursive flag is
// so that any existing netns bindmounts are carried over.
err = unix.Mount(nsRunDir, nsRunDir, "none", unix.MS_BIND|unix.MS_REC, "")
if err != nil {
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index 9e0dcb728..dc577890a 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -178,6 +178,11 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
return entities.ListContainer{}, err
}
+ networks, _, err := ctr.Networks()
+ if err != nil {
+ return entities.ListContainer{}, err
+ }
+
ps := entities.ListContainer{
AutoRemove: ctr.AutoRemove(),
Command: conConfig.Command,
@@ -192,6 +197,7 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
Labels: conConfig.Labels,
Mounts: ctr.UserVolumes(),
Names: []string{conConfig.Name},
+ Networks: networks,
Pid: pid,
Pod: conConfig.Pod,
Ports: portMappings,
diff --git a/pkg/rootless/rootless.go b/pkg/rootless/rootless.go
index 799c793d8..df35c0d6b 100644
--- a/pkg/rootless/rootless.go
+++ b/pkg/rootless/rootless.go
@@ -2,10 +2,12 @@ package rootless
import (
"os"
+ "sort"
"sync"
"github.com/containers/storage"
"github.com/opencontainers/runc/libcontainer/user"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@@ -50,24 +52,151 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) {
}
var (
- availableGids int64
- availableGidsErr error
- availableGidsOnce sync.Once
+ uidMap []user.IDMap
+ uidMapError error
+ uidMapOnce sync.Once
+
+ gidMap []user.IDMap
+ gidMapError error
+ gidMapOnce sync.Once
)
-// GetAvailableGids returns how many GIDs are available in the
+// GetAvailableUidMap returns the UID mappings in the
// current user namespace.
-func GetAvailableGids() (int64, error) {
- availableGidsOnce.Do(func() {
- idMap, err := user.ParseIDMapFile("/proc/self/gid_map")
+func GetAvailableUidMap() ([]user.IDMap, error) {
+ uidMapOnce.Do(func() {
+ var err error
+ uidMap, err = user.ParseIDMapFile("/proc/self/uid_map")
if err != nil {
- availableGidsErr = err
+ uidMapError = err
return
}
- availableGids = int64(0)
- for _, r := range idMap {
- availableGids += r.Count
+ })
+ return uidMap, uidMapError
+}
+
+// GetAvailableGidMap returns the GID mappings in the
+// current user namespace.
+func GetAvailableGidMap() ([]user.IDMap, error) {
+ gidMapOnce.Do(func() {
+ var err error
+ gidMap, err = user.ParseIDMapFile("/proc/self/gid_map")
+ if err != nil {
+ gidMapError = err
+ return
}
})
- return availableGids, availableGidsErr
+ return gidMap, gidMapError
+}
+
+// GetAvailableIDMaps returns the UID and GID mappings in the
+// current user namespace.
+func GetAvailableIDMaps() ([]user.IDMap, []user.IDMap, error) {
+ u, err := GetAvailableUidMap()
+ if err != nil {
+ return nil, nil, err
+ }
+ g, err := GetAvailableGidMap()
+ if err != nil {
+ return nil, nil, err
+ }
+ return u, g, nil
+}
+
+func countAvailableIDs(mappings []user.IDMap) int64 {
+ availableUids := int64(0)
+ for _, r := range mappings {
+ availableUids += r.Count
+ }
+ return availableUids
+}
+
+// GetAvailableUids returns how many UIDs are available in the
+// current user namespace.
+func GetAvailableUids() (int64, error) {
+ uids, err := GetAvailableUidMap()
+ if err != nil {
+ return -1, err
+ }
+
+ return countAvailableIDs(uids), nil
+}
+
+// GetAvailableGids returns how many GIDs are available in the
+// current user namespace.
+func GetAvailableGids() (int64, error) {
+ gids, err := GetAvailableGidMap()
+ if err != nil {
+ return -1, err
+ }
+
+ return countAvailableIDs(gids), nil
+}
+
+// findIDInMappings find the the mapping that contains the specified ID.
+// It assumes availableMappings is sorted by ID.
+func findIDInMappings(id int64, availableMappings []user.IDMap) *user.IDMap {
+ i := sort.Search(len(availableMappings), func(i int) bool {
+ return availableMappings[i].ID >= id
+ })
+ if i < 0 || i >= len(availableMappings) {
+ return nil
+ }
+ r := &availableMappings[i]
+ if id >= r.ID && id < r.ID+r.Count {
+ return r
+ }
+ return nil
+}
+
+// MaybeSplitMappings checks whether the specified OCI mappings are possible
+// in the current user namespace or the specified ranges must be split.
+func MaybeSplitMappings(mappings []spec.LinuxIDMapping, availableMappings []user.IDMap) []spec.LinuxIDMapping {
+ var ret []spec.LinuxIDMapping
+ var overflow spec.LinuxIDMapping
+ overflow.Size = 0
+ consumed := 0
+ sort.Slice(availableMappings, func(i, j int) bool {
+ return availableMappings[i].ID < availableMappings[j].ID
+ })
+ for {
+ cur := overflow
+ // if there is no overflow left from the previous request, get the next one
+ if cur.Size == 0 {
+ if consumed == len(mappings) {
+ // all done
+ return ret
+ }
+ cur = mappings[consumed]
+ consumed++
+ }
+
+ // Find the range where the first specified ID is present
+ r := findIDInMappings(int64(cur.HostID), availableMappings)
+ if r == nil {
+ // The requested range is not available. Just return the original request
+ // and let other layers deal with it.
+ return mappings
+ }
+
+ offsetInRange := cur.HostID - uint32(r.ID)
+
+ usableIDs := uint32(r.Count) - offsetInRange
+
+ // the current range can satisfy the whole request
+ if usableIDs >= cur.Size {
+ // reset the overflow
+ overflow.Size = 0
+ } else {
+ // the current range can satisfy the request partially
+ // so move the rest to overflow
+ overflow.Size = cur.Size - usableIDs
+ overflow.ContainerID = cur.ContainerID + usableIDs
+ overflow.HostID = cur.HostID + usableIDs
+
+ // and cap to the usableIDs count
+ cur.Size = usableIDs
+ }
+ ret = append(ret, cur)
+ }
}
diff --git a/pkg/rootless/rootless_test.go b/pkg/rootless/rootless_test.go
new file mode 100644
index 000000000..ef574099c
--- /dev/null
+++ b/pkg/rootless/rootless_test.go
@@ -0,0 +1,101 @@
+package rootless
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/opencontainers/runc/libcontainer/user"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+func TestMaybeSplitMappings(t *testing.T) {
+ mappings := []spec.LinuxIDMapping{
+ {
+ ContainerID: 0,
+ HostID: 0,
+ Size: 2,
+ },
+ }
+ desiredMappings := []spec.LinuxIDMapping{
+ {
+ ContainerID: 0,
+ HostID: 0,
+ Size: 1,
+ },
+ {
+ ContainerID: 1,
+ HostID: 1,
+ Size: 1,
+ },
+ }
+ availableMappings := []user.IDMap{
+ {
+ ID: 1,
+ ParentID: 1000000,
+ Count: 65536,
+ },
+ {
+ ID: 0,
+ ParentID: 1000,
+ Count: 1,
+ },
+ }
+ newMappings := MaybeSplitMappings(mappings, availableMappings)
+ if !reflect.DeepEqual(newMappings, desiredMappings) {
+ t.Fatal("wrong mappings generated")
+ }
+
+ mappings = []spec.LinuxIDMapping{
+ {
+ ContainerID: 0,
+ HostID: 0,
+ Size: 2,
+ },
+ }
+ desiredMappings = []spec.LinuxIDMapping{
+ {
+ ContainerID: 0,
+ HostID: 0,
+ Size: 2,
+ },
+ }
+ availableMappings = []user.IDMap{
+ {
+ ID: 0,
+ ParentID: 1000000,
+ Count: 65536,
+ },
+ }
+ newMappings = MaybeSplitMappings(mappings, availableMappings)
+
+ if !reflect.DeepEqual(newMappings, desiredMappings) {
+ t.Fatal("wrong mappings generated")
+ }
+
+ mappings = []spec.LinuxIDMapping{
+ {
+ ContainerID: 0,
+ HostID: 0,
+ Size: 1,
+ },
+ }
+ desiredMappings = []spec.LinuxIDMapping{
+ {
+ ContainerID: 0,
+ HostID: 0,
+ Size: 1,
+ },
+ }
+ availableMappings = []user.IDMap{
+ {
+ ID: 10000,
+ ParentID: 10000,
+ Count: 65536,
+ },
+ }
+
+ newMappings = MaybeSplitMappings(mappings, availableMappings)
+ if !reflect.DeepEqual(newMappings, desiredMappings) {
+ t.Fatal("wrong mappings generated")
+ }
+}
diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go
index 67638e30a..45c9d5af1 100644
--- a/pkg/signal/signal_linux_mipsx.go
+++ b/pkg/signal/signal_linux_mipsx.go
@@ -19,6 +19,8 @@ import (
const (
sigrtmin = 34
sigrtmax = 127
+
+ SIGWINCH = syscall.SIGWINCH
)
// signalMap is a map of Linux signals.
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index 42fea0277..2feb1d3b2 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -100,15 +100,9 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
if err != nil {
return nil, err
}
- // First transform the os env into a map. We need it for the labels later in
- // any case.
- osEnv, err := envLib.ParseSlice(os.Environ())
- if err != nil {
- return nil, errors.Wrap(err, "error parsing host environment variables")
- }
// Get Default Environment from containers.conf
- defaultEnvs, err := envLib.ParseSlice(rtc.GetDefaultEnv())
+ defaultEnvs, err := envLib.ParseSlice(rtc.GetDefaultEnvEx(s.EnvHost, s.HTTPProxy))
if err != nil {
return nil, errors.Wrap(err, "error parsing fields in containers.conf")
}
@@ -133,6 +127,12 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
defaultEnvs = envLib.Join(defaultEnvs, envs)
}
+ // First transform the os env into a map. We need it for the labels later in
+ // any case.
+ osEnv, err := envLib.ParseSlice(os.Environ())
+ if err != nil {
+ return nil, errors.Wrap(err, "error parsing host environment variables")
+ }
// Caller Specified defaults
if s.EnvHost {
defaultEnvs = envLib.Join(defaultEnvs, osEnv)
@@ -282,8 +282,8 @@ func finishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(statT.Rdev)))
- v.Minor = (int64(unix.Minor(statT.Rdev)))
+ v.Major = (int64(unix.Major(uint64(statT.Rdev))))
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev))))
s.ResourceLimits.BlockIO.ThrottleReadBpsDevice = append(s.ResourceLimits.BlockIO.ThrottleReadBpsDevice, v)
}
}
@@ -293,8 +293,8 @@ func finishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(statT.Rdev)))
- v.Minor = (int64(unix.Minor(statT.Rdev)))
+ v.Major = (int64(unix.Major(uint64(statT.Rdev))))
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev))))
s.ResourceLimits.BlockIO.ThrottleWriteBpsDevice = append(s.ResourceLimits.BlockIO.ThrottleWriteBpsDevice, v)
}
}
@@ -304,8 +304,8 @@ func finishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(statT.Rdev)))
- v.Minor = (int64(unix.Minor(statT.Rdev)))
+ v.Major = (int64(unix.Major(uint64(statT.Rdev))))
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev))))
s.ResourceLimits.BlockIO.ThrottleReadIOPSDevice = append(s.ResourceLimits.BlockIO.ThrottleReadIOPSDevice, v)
}
}
@@ -315,8 +315,8 @@ func finishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(statT.Rdev)))
- v.Minor = (int64(unix.Minor(statT.Rdev)))
+ v.Major = (int64(unix.Major(uint64(statT.Rdev))))
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev))))
s.ResourceLimits.BlockIO.ThrottleWriteIOPSDevice = append(s.ResourceLimits.BlockIO.ThrottleWriteIOPSDevice, v)
}
}
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index 9fceec7b3..390b19beb 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -133,13 +133,13 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
configSpec := g.Config
configSpec.Process.Capabilities.Ambient = []string{}
configSpec.Process.Capabilities.Bounding = caplist
- configSpec.Process.Capabilities.Inheritable = caplist
user := strings.Split(s.User, ":")[0]
if (user == "" && s.UserNS.NSMode != specgen.KeepID) || user == "root" || user == "0" {
configSpec.Process.Capabilities.Effective = caplist
configSpec.Process.Capabilities.Permitted = caplist
+ configSpec.Process.Capabilities.Inheritable = caplist
} else {
userCaps, err := capabilities.MergeCapabilities(nil, s.CapAdd, nil)
if err != nil {
@@ -147,6 +147,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
}
configSpec.Process.Capabilities.Effective = userCaps
configSpec.Process.Capabilities.Permitted = userCaps
+ configSpec.Process.Capabilities.Inheritable = userCaps
// Ambient capabilities were added to Linux 4.3. Set ambient
// capabilities only when the kernel supports them.
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index 19630f124..c8e65bfe3 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -53,7 +53,7 @@ TimeoutStopSec=82
ExecStart=/usr/bin/podman start 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
ExecStop=/usr/bin/podman stop -t 22 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
ExecStopPost=/usr/bin/podman stop -t 22 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
Type=forking
[Install]
@@ -76,7 +76,7 @@ TimeoutStopSec=70
ExecStart=/usr/bin/podman start foobar
ExecStop=/usr/bin/podman stop -t 10 foobar
ExecStopPost=/usr/bin/podman stop -t 10 foobar
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
Type=forking
[Install]
@@ -101,7 +101,7 @@ TimeoutStopSec=70
ExecStart=/usr/bin/podman start foobar
ExecStop=/usr/bin/podman stop -t 10 foobar
ExecStopPost=/usr/bin/podman stop -t 10 foobar
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
Type=forking
[Install]
@@ -343,7 +343,7 @@ WantedBy=multi-user.target default.target
ServiceName: "container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
ContainerNameOrID: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 22,
PodmanVersion: "CI",
EnvVariable: EnvVariable,
@@ -358,7 +358,7 @@ WantedBy=multi-user.target default.target
ServiceName: "container-foobar",
ContainerNameOrID: "foobar",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
EnvVariable: EnvVariable,
@@ -373,7 +373,7 @@ WantedBy=multi-user.target default.target
ServiceName: "container-foobar",
ContainerNameOrID: "foobar",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
BoundToServices: []string{"pod", "a", "b", "c"},
@@ -388,7 +388,7 @@ WantedBy=multi-user.target default.target
Executable: "/usr/bin/podman",
ServiceName: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
RestartPolicy: "never",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
EnvVariable: EnvVariable,
@@ -403,7 +403,7 @@ WantedBy=multi-user.target default.target
ServiceName: "jadda-jadda",
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "container", "run", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN", "foo=arg \"with \" space"},
@@ -419,7 +419,7 @@ WantedBy=multi-user.target default.target
ServiceName: "jadda-jadda",
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "run", "-d", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
@@ -435,7 +435,7 @@ WantedBy=multi-user.target default.target
ServiceName: "jadda-jadda",
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "run", "-d", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
@@ -454,7 +454,7 @@ WantedBy=multi-user.target default.target
ServiceName: "jadda-jadda",
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "run", "--detach", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
@@ -470,7 +470,7 @@ WantedBy=multi-user.target default.target
ServiceName: "container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
ContainerNameOrID: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "run", "awesome-image:latest"},
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index b1d122d0e..c0d98df45 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -55,7 +55,7 @@ TimeoutStopSec=102
ExecStart=/usr/bin/podman start jadda-jadda-infra
ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
Type=forking
[Install]
@@ -156,7 +156,7 @@ WantedBy=multi-user.target default.target
ServiceName: "pod-123abc",
InfraNameOrID: "jadda-jadda-infra",
RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 42,
PodmanVersion: "CI",
RequiredServices: []string{"container-1", "container-2"},
@@ -188,7 +188,7 @@ WantedBy=multi-user.target default.target
ServiceName: "pod-123abc",
InfraNameOrID: "jadda-jadda-infra",
RestartPolicy: "on-failure",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 10,
PodmanVersion: "CI",
RequiredServices: []string{"container-1", "container-2"},
diff --git a/test/apiv2/rest_api/test_rest_v2_0_0.py b/test/apiv2/rest_api/test_rest_v2_0_0.py
index 2f9e62149..cc66dd5af 100644
--- a/test/apiv2/rest_api/test_rest_v2_0_0.py
+++ b/test/apiv2/rest_api/test_rest_v2_0_0.py
@@ -1,13 +1,15 @@
import json
+import os
import random
+import shutil
import string
import subprocess
+import sys
+import time
import unittest
from multiprocessing import Process
import requests
-import sys
-import time
from dateutil.parser import parse
from test.apiv2.rest_api import Podman
@@ -449,7 +451,7 @@ class TestApi(unittest.TestCase):
self.assertEqual(inspect.status_code, 404, inspect.content)
prune = requests.post(PODMAN_URL + "/v1.40/networks/prune")
- self.assertEqual(prune.status_code, 405, prune.content)
+ self.assertEqual(prune.status_code, 404, prune.content)
def test_volumes_compat(self):
name = "Volume_" + "".join(random.choice(string.ascii_letters) for i in range(10))
@@ -499,8 +501,18 @@ class TestApi(unittest.TestCase):
rm = requests.delete(PODMAN_URL + f"/v1.40/volumes/{name}")
self.assertEqual(rm.status_code, 204, rm.content)
+ # recreate volume with data and then prune it
+ r = requests.post(PODMAN_URL + "/v1.40/volumes/create", json={"Name": name})
+ self.assertEqual(create.status_code, 201, create.content)
+ create = json.loads(r.content)
+ with open(os.path.join(create["Mountpoint"], "test_prune"), "w") as file:
+ file.writelines(["This is a test\n", "This is a good test\n"])
+
prune = requests.post(PODMAN_URL + "/v1.40/volumes/prune")
self.assertEqual(prune.status_code, 200, prune.content)
+ payload = json.loads(prune.content)
+ self.assertIn(name, payload["VolumesDeleted"])
+ self.assertGreater(payload["SpaceReclaimed"], 0)
def test_auth_compat(self):
r = requests.post(
@@ -530,6 +542,50 @@ class TestApi(unittest.TestCase):
self.assertIn("Volumes", obj)
self.assertIn("BuildCache", obj)
+ def test_prune_compat(self):
+ name = "Ctnr_" + "".join(random.choice(string.ascii_letters) for i in range(10))
+
+ r = requests.post(
+ PODMAN_URL + f"/v1.40/containers/create?name={name}",
+ json={
+ "Cmd": ["cp", "/etc/motd", "/motd.size_test"],
+ "Image": "alpine:latest",
+ "NetworkDisabled": True,
+ },
+ )
+ self.assertEqual(r.status_code, 201, r.text)
+ create = json.loads(r.text)
+
+ r = requests.post(PODMAN_URL + f"/v1.40/containers/{create['Id']}/start")
+ self.assertEqual(r.status_code, 204, r.text)
+
+ r = requests.post(PODMAN_URL + f"/v1.40/containers/{create['Id']}/wait")
+ self.assertEqual(r.status_code, 200, r.text)
+ wait = json.loads(r.text)
+ self.assertEqual(wait["StatusCode"], 0, wait["Error"]["Message"])
+
+ prune = requests.post(PODMAN_URL + "/v1.40/containers/prune")
+ self.assertEqual(prune.status_code, 200, prune.status_code)
+ prune_payload = json.loads(prune.text)
+ self.assertGreater(prune_payload["SpaceReclaimed"], 0)
+ self.assertIn(create["Id"], prune_payload["ContainersDeleted"])
+
+ # Delete any orphaned containers
+ r = requests.get(PODMAN_URL + "/v1.40/containers/json?all=true")
+ self.assertEqual(r.status_code, 200, r.text)
+ for ctnr in json.loads(r.text):
+ requests.delete(PODMAN_URL + f"/v1.40/containers/{ctnr['Id']}?force=true")
+
+ prune = requests.post(PODMAN_URL + "/v1.40/images/prune")
+ self.assertEqual(prune.status_code, 200, prune.text)
+ prune_payload = json.loads(prune.text)
+ self.assertGreater(prune_payload["SpaceReclaimed"], 0)
+
+ # FIXME need method to determine which image is going to be "pruned" to fix test
+ # TODO should handler be recursive when deleting images?
+ # self.assertIn(img["Id"], prune_payload["ImagesDeleted"][1]["Deleted"])
+ self.assertIsNotNone(prune_payload["ImagesDeleted"][1]["Deleted"])
+
if __name__ == "__main__":
unittest.main()
diff --git a/test/e2e/build/basicalpine/Containerfile.volume b/test/e2e/build/basicalpine/Containerfile.volume
new file mode 100644
index 000000000..6a4fc8242
--- /dev/null
+++ b/test/e2e/build/basicalpine/Containerfile.volume
@@ -0,0 +1,2 @@
+FROM alpine
+VOLUME "/volume0"
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 75310b961..abc37792a 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -4,6 +4,7 @@ import (
"net"
"os"
"os/exec"
+ "strings"
"github.com/containers/podman/v2/pkg/criu"
. "github.com/containers/podman/v2/test/utils"
@@ -652,4 +653,173 @@ var _ = Describe("Podman checkpoint", func() {
// Remove exported checkpoint
os.Remove(fileName)
})
+
+ It("podman checkpoint a container with volumes", func() {
+ session := podmanTest.Podman([]string{
+ "build", "-f", "build/basicalpine/Containerfile.volume", "-t", "test-cr-volume",
+ })
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Start the container
+ localRunString := getRunString([]string{
+ "--rm",
+ "-v", "/volume1",
+ "-v", "my-test-vol:/volume2",
+ "test-cr-volume",
+ "top",
+ })
+ session = podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+
+ cid := session.OutputToString()
+
+ // Add file in volume0
+ result := podmanTest.Podman([]string{
+ "exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /volume0/test.output",
+ })
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+
+ // Add file in volume1
+ result = podmanTest.Podman([]string{
+ "exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /volume1/test.output",
+ })
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+
+ // Add file in volume2
+ result = podmanTest.Podman([]string{
+ "exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /volume2/test.output",
+ })
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+
+ checkpointFileName := "/tmp/checkpoint-" + cid + ".tar.gz"
+
+ // Checkpoint the container
+ result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", checkpointFileName})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(0))
+
+ // Restore container should fail because named volume still exists
+ result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
+ result.WaitWithDefaultTimeout()
+ Expect(result).To(ExitWithError())
+ Expect(result.ErrorToString()).To(ContainSubstring(
+ "volume with name my-test-vol already exists. Use --ignore-volumes to not restore content of volumes",
+ ))
+
+ // Remove named volume
+ session = podmanTest.Podman([]string{"volume", "rm", "my-test-vol"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Restoring container
+ result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ // Validate volume0 content
+ result = podmanTest.Podman([]string{"exec", "-l", "cat", "/volume0/test.output"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
+
+ // Validate volume1 content
+ result = podmanTest.Podman([]string{"exec", "-l", "cat", "/volume1/test.output"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
+
+ // Validate volume2 content
+ result = podmanTest.Podman([]string{"exec", "-l", "cat", "/volume2/test.output"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
+
+ // Remove exported checkpoint
+ os.Remove(checkpointFileName)
+ })
+
+ It("podman checkpoint container with --pre-checkpoint", func() {
+ if !strings.Contains(podmanTest.OCIRuntime, "runc") {
+ Skip("Test only works on runc 1.0-rc3 or higher.")
+ }
+ localRunString := getRunString([]string{ALPINE, "top"})
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ cid := session.OutputToString()
+
+ result := podmanTest.Podman([]string{"container", "checkpoint", "-P", cid})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ result = podmanTest.Podman([]string{"container", "checkpoint", "--with-previous", cid})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
+
+ result = podmanTest.Podman([]string{"container", "restore", cid})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+ })
+
+ It("podman checkpoint container with --pre-checkpoint and export (migration)", func() {
+ if !strings.Contains(podmanTest.OCIRuntime, "runc") {
+ Skip("Test only works on runc 1.0-rc3 or higher.")
+ }
+ localRunString := getRunString([]string{ALPINE, "top"})
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ cid := session.OutputToString()
+ preCheckpointFileName := "/tmp/pre-checkpoint-" + cid + ".tar.gz"
+ checkpointFileName := "/tmp/checkpoint-" + cid + ".tar.gz"
+
+ result := podmanTest.Podman([]string{"container", "checkpoint", "-P", "-e", preCheckpointFileName, cid})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ result = podmanTest.Podman([]string{"container", "checkpoint", "--with-previous", "-e", checkpointFileName, cid})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
+
+ result = podmanTest.Podman([]string{"rm", "-f", cid})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+
+ result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName, "--import-previous", preCheckpointFileName})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ os.Remove(checkpointFileName)
+ os.Remove(preCheckpointFileName)
+ })
})
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index a076ada6b..18679dd53 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -378,10 +378,17 @@ func GetRandomIPAddress() string {
// RunTopContainer runs a simple container in the background that
// runs top. If the name passed != "", it will have a name
func (p *PodmanTestIntegration) RunTopContainer(name string) *PodmanSessionIntegration {
+ return p.RunTopContainerWithArgs(name, nil)
+}
+
+// RunTopContainerWithArgs runs a simple container in the background that
+// runs top. If the name passed != "", it will have a name, command args can also be passed in
+func (p *PodmanTestIntegration) RunTopContainerWithArgs(name string, args []string) *PodmanSessionIntegration {
var podmanArgs = []string{"run"}
if name != "" {
podmanArgs = append(podmanArgs, "--name", name)
}
+ podmanArgs = append(podmanArgs, args...)
podmanArgs = append(podmanArgs, "-d", ALPINE, "top")
return p.Podman(podmanArgs)
}
@@ -538,12 +545,7 @@ func (p *PodmanTestIntegration) CreatePodWithLabels(name string, labels map[stri
}
func (p *PodmanTestIntegration) RunTopContainerInPod(name, pod string) *PodmanSessionIntegration {
- var podmanArgs = []string{"run", "--pod", pod}
- if name != "" {
- podmanArgs = append(podmanArgs, "--name", name)
- }
- podmanArgs = append(podmanArgs, "-d", ALPINE, "top")
- return p.Podman(podmanArgs)
+ return p.RunTopContainerWithArgs(name, []string{"--pod", pod})
}
func (p *PodmanTestIntegration) RunHealthCheck(cid string) error {
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index 18737105e..b180d881a 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -120,18 +120,200 @@ var _ = Describe("Podman exec", func() {
})
It("podman exec --privileged", func() {
- hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
- Expect(hostCap.ExitCode()).To(Equal(0))
+ session := podmanTest.Podman([]string{"run", "--privileged", "--rm", ALPINE, "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ bndPerms := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"run", "--privileged", "--rm", ALPINE, "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ effPerms := session.OutputToString()
+
+ setup := podmanTest.RunTopContainer("test-privileged")
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(effPerms))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bndPerms))
+
+ })
+
+ It("podman exec --privileged", func() {
+ session := podmanTest.Podman([]string{"run", "--privileged", "--user=bin", "--rm", ALPINE, "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ bndPerms := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"run", "--privileged", "--user=bin", "--rm", ALPINE, "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ effPerms := session.OutputToString()
+
+ setup := podmanTest.RunTopContainer("test-privileged")
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "--user=bin", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(effPerms))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "--user=bin", "test-privileged", "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bndPerms))
+
+ })
+
+ It("podman exec --privileged", func() {
+ session := podmanTest.Podman([]string{"run", "--privileged", "--rm", ALPINE, "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ bndPerms := session.OutputToString()
setup := podmanTest.RunTopContainer("test-privileged")
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session = podmanTest.Podman([]string{"exec", "--privileged", "--user=bin", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("00000000"))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "--user=bin", "test-privileged", "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bndPerms))
+ })
- containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
+ It("podman exec --privileged container not running as root", func() {
+ session := podmanTest.Podman([]string{"run", "--privileged", "--rm", ALPINE, "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ bndPerms := session.OutputToString()
+
+ setup := podmanTest.RunTopContainerWithArgs("test-privileged", []string{"--user=bin"})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("00000000"))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "--user=bin", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("00000000"))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "--user=root", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bndPerms))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "--user=bin", "test-privileged", "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bndPerms))
+ })
+
+ It("podman exec with user with cap-add", func() {
+ capAdd := "--cap-add=net_bind_service"
+ session := podmanTest.Podman([]string{"run", "--user=bin", capAdd, "--rm", ALPINE, "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ bndPerms := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"run", "--user=bin", capAdd, "--rm", ALPINE, "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ effPerms := session.OutputToString()
+
+ setup := podmanTest.RunTopContainerWithArgs("test-privileged", []string{"--user=bin", capAdd})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"exec", "test-privileged", "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bndPerms))
+
+ session = podmanTest.Podman([]string{"exec", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(effPerms))
+ })
+
+ It("podman exec with user with and cap-drop cap-add", func() {
+ capAdd := "--cap-add=net_bind_service"
+ capDrop := "--cap-drop=all"
+ session := podmanTest.Podman([]string{"run", "--user=bin", capDrop, capAdd, "--rm", ALPINE, "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ bndPerms := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"run", "--user=bin", capDrop, capAdd, "--rm", ALPINE, "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ effPerms := session.OutputToString()
+
+ setup := podmanTest.RunTopContainerWithArgs("test-privileged", []string{"--user=bin", capDrop, capAdd})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"exec", "test-privileged", "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bndPerms))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapInh /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(effPerms))
+
+ session = podmanTest.Podman([]string{"exec", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(effPerms))
+
+ session = podmanTest.Podman([]string{"exec", "test-privileged", "sh", "-c", "grep ^CapPrm /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(effPerms))
+
+ session = podmanTest.Podman([]string{"exec", "test-privileged", "sh", "-c", "grep ^CapAmb /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(effPerms))
+ })
+
+ It("podman exec --privileged with user", func() {
+ session := podmanTest.Podman([]string{"run", "--privileged", "--user=bin", "--rm", ALPINE, "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ bindPerms := session.OutputToString()
+
+ setup := podmanTest.RunTopContainerWithArgs("test-privileged", []string{"--privileged", "--user=bin"})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapBnd /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(bindPerms))
+
+ session = podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
})
It("podman exec terminal doesn't hang", func() {
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 225da785c..9f63c1d5d 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -6,6 +6,7 @@ import (
"sort"
. "github.com/containers/podman/v2/test/utils"
+ "github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
@@ -280,6 +281,69 @@ var _ = Describe("Podman ps", func() {
Expect(session.OutputToString()).To(Not(ContainSubstring(podid3)))
})
+ It("podman pod ps filter network", func() {
+ net := stringid.GenerateNonCryptoID()
+ session := podmanTest.Podman([]string{"network", "create", net})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(net)
+
+ session = podmanTest.Podman([]string{"pod", "create", "--network", net})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ podWithNet := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"pod", "create"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ podWithoutNet := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"pod", "ps", "--no-trunc", "--filter", "network=" + net})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(podWithNet))
+ Expect(session.OutputToString()).To(Not(ContainSubstring(podWithoutNet)))
+ })
+
+ It("podman pod ps --format networks", func() {
+ session := podmanTest.Podman([]string{"pod", "create"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+
+ session = podmanTest.Podman([]string{"pod", "ps", "--format", "{{ .Networks }}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ if isRootless() {
+ // rootless container don't have a network by default
+ Expect(session.OutputToString()).To(Equal(""))
+ } else {
+ // default network name is podman
+ Expect(session.OutputToString()).To(Equal("podman"))
+ }
+
+ net1 := stringid.GenerateNonCryptoID()
+ session = podmanTest.Podman([]string{"network", "create", net1})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(net1)
+ net2 := stringid.GenerateNonCryptoID()
+ session = podmanTest.Podman([]string{"network", "create", net2})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(net2)
+
+ session = podmanTest.Podman([]string{"pod", "create", "--network", net1 + "," + net2})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ pid := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"pod", "ps", "--format", "{{ .Networks }}", "--filter", "id=" + pid})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ // the output is not deterministic so check both possible orders
+ Expect(session.OutputToString()).To(Or(Equal(net1+","+net2), Equal(net2+","+net1)))
+ })
+
It("pod no infra should ps", func() {
session := podmanTest.Podman([]string{"pod", "create", "--infra=false"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 0c5d817ba..13701fc3b 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -8,6 +8,7 @@ import (
"strings"
. "github.com/containers/podman/v2/test/utils"
+ "github.com/containers/storage/pkg/stringid"
"github.com/docker/go-units"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -724,4 +725,67 @@ var _ = Describe("Podman ps", func() {
})
+ It("podman ps filter network", func() {
+ net := stringid.GenerateNonCryptoID()
+ session := podmanTest.Podman([]string{"network", "create", net})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(net)
+
+ session = podmanTest.Podman([]string{"create", "--network", net, ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ ctrWithNet := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"create", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ ctrWithoutNet := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"ps", "--all", "--no-trunc", "--filter", "network=" + net})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(ctrWithNet))
+ Expect(session.OutputToString()).To(Not(ContainSubstring(ctrWithoutNet)))
+ })
+
+ It("podman ps --format networks", func() {
+ session := podmanTest.Podman([]string{"create", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+
+ session = podmanTest.Podman([]string{"ps", "--all", "--format", "{{ .Networks }}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ if isRootless() {
+ // rootless container don't have a network by default
+ Expect(session.OutputToString()).To(Equal(""))
+ } else {
+ // default network name is podman
+ Expect(session.OutputToString()).To(Equal("podman"))
+ }
+
+ net1 := stringid.GenerateNonCryptoID()
+ session = podmanTest.Podman([]string{"network", "create", net1})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(net1)
+ net2 := stringid.GenerateNonCryptoID()
+ session = podmanTest.Podman([]string{"network", "create", net2})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(net2)
+
+ session = podmanTest.Podman([]string{"create", "--network", net1 + "," + net2, ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ cid := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"ps", "--all", "--format", "{{ .Networks }}", "--filter", "id=" + cid})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ // the output is not deterministic so check both possible orders
+ Expect(session.OutputToString()).To(Or(Equal(net1+","+net2), Equal(net2+","+net1)))
+ })
+
})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 92d7d222e..19060ecdc 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -342,6 +342,11 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+ session = podmanTest.Podman([]string{"run", "--rm", "--user", "bin", ALPINE, "grep", "CapInh", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+
session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapBnd", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -352,6 +357,11 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb"))
+ session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapInh", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb"))
+
session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "grep", "CapBnd", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -367,10 +377,10 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
- session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
+ session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
session = podmanTest.Podman([]string{"run", "--user=0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
session.WaitWithDefaultTimeout()
@@ -382,6 +392,11 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+ session = podmanTest.Podman([]string{"run", "--user=0:0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb"))
+
if os.Geteuid() > 0 {
if os.Getenv("SKIP_USERNS") != "" {
Skip("Skip userns tests.")
@@ -393,6 +408,16 @@ var _ = Describe("Podman run", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
+
+ session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--privileged", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+
+ session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
}
})
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index f809c5afe..1d86ae744 100644
--- a/test/e2e/search_test.go
+++ b/test/e2e/search_test.go
@@ -124,6 +124,16 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search.OutputToString()).To(ContainSubstring("docker.io/library/alpine"))
})
+ It("podman search format json list tags", func() {
+ search := podmanTest.Podman([]string{"search", "--list-tags", "--format", "json", "alpine"})
+ search.WaitWithDefaultTimeout()
+ Expect(search.ExitCode()).To(Equal(0))
+ Expect(search.IsJSONOutputValid()).To(BeTrue())
+ Expect(search.OutputToString()).To(ContainSubstring("docker.io/library/alpine"))
+ Expect(search.OutputToString()).To(ContainSubstring("3.10"))
+ Expect(search.OutputToString()).To(ContainSubstring("2.7"))
+ })
+
It("podman search no-trunc flag", func() {
search := podmanTest.Podman([]string{"search", "--no-trunc", "alpine"})
search.WaitWithDefaultTimeout()
diff --git a/test/system/010-images.bats b/test/system/010-images.bats
index 76caf282b..e7c88408e 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -228,4 +228,17 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
run_podman rmi ${aaa_name}:${aaa_tag} ${zzz_name}:${zzz_tag}
}
+# Regression test for #8931
+@test "podman images - bare manifest list" {
+ # Create an empty manifest list and list images.
+
+ run_podman inspect --format '{{.ID}}' $IMAGE
+ iid=$output
+
+ run_podman manifest create test:1.0
+ run_podman images --format '{{.ID}}' --no-trunc
+ [[ "$output" == *"sha256:$iid"* ]]
+
+ run_podman rmi test:1.0
+}
# vim: filetype=sh
diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats
index 20fdd068f..6a89247e6 100644
--- a/test/system/400-unprivileged-access.bats
+++ b/test/system/400-unprivileged-access.bats
@@ -75,7 +75,7 @@ EOF
is "$output" "/var/lib/containers/storage" "GraphRoot in expected place"
GRAPH_ROOT="$output"
run_podman info --format '{{.Store.RunRoot}}'
- is "$output" "/var/run/containers/storage" "RunRoot in expected place"
+ is "$output" ".*/run/containers/storage" "RunRoot in expected place"
RUN_ROOT="$output"
# The main test: find all world-writable files or directories underneath
diff --git a/troubleshooting.md b/troubleshooting.md
index 78e22fa2f..c028a7714 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -344,7 +344,7 @@ After creating a container with Podman's storage directories mounted in from the
When running Podman inside a container, it is recommended to mount at a minimum `/var/lib/containers/storage/` as a volume.
Typically, you will not mount in the host version of the directory, but if you wish to share containers with the host, you can do so.
-If you do mount in the host's `/var/lib/containers/storage`, however, you must also mount in the host's `/var/run/libpod` and `/var/run/containers/storage` directories.
+If you do mount in the host's `/var/lib/containers/storage`, however, you must also mount in the host's `/run/libpod` and `/run/containers/storage` directories.
Not doing this will cause Podman in the container to detect that temporary files have been cleared, leading it to assume a system restart has taken place.
This can cause Podman to reset container states and lose track of running containers.
diff --git a/vendor/github.com/containers/buildah/Makefile b/vendor/github.com/containers/buildah/Makefile
index 45f8a8ec8..2768a2917 100644
--- a/vendor/github.com/containers/buildah/Makefile
+++ b/vendor/github.com/containers/buildah/Makefile
@@ -1,9 +1,8 @@
export GOPROXY=https://proxy.golang.org
-SELINUXTAG := $(shell ./selinux_tag.sh)
APPARMORTAG := $(shell hack/apparmor_tag.sh)
STORAGETAGS := $(shell ./btrfs_tag.sh) $(shell ./btrfs_installed_tag.sh) $(shell ./libdm_tag.sh)
-SECURITYTAGS ?= seccomp $(SELINUXTAG) $(APPARMORTAG)
+SECURITYTAGS ?= seccomp $(APPARMORTAG)
TAGS ?= $(SECURITYTAGS) $(STORAGETAGS)
BUILDTAGS += $(TAGS)
PREFIX := /usr/local
@@ -52,7 +51,7 @@ all: bin/buildah bin/imgtype docs
# Update nix/nixpkgs.json its latest stable commit
.PHONY: nixpkgs
nixpkgs:
- @nix run -f channel:nixos-20.03 nix-prefetch-git -c nix-prefetch-git \
+ @nix run -f channel:nixos-20.09 nix-prefetch-git -c nix-prefetch-git \
--no-deepClone https://github.com/nixos/nixpkgs > nix/nixpkgs.json
# Build statically linked binary
diff --git a/vendor/github.com/containers/buildah/chroot/selinux.go b/vendor/github.com/containers/buildah/chroot/selinux.go
index 08e8f998b..ef96a0e7a 100644
--- a/vendor/github.com/containers/buildah/chroot/selinux.go
+++ b/vendor/github.com/containers/buildah/chroot/selinux.go
@@ -1,4 +1,4 @@
-// +build linux,selinux
+// +build linux
package chroot
diff --git a/vendor/github.com/containers/buildah/chroot/selinux_unsupported.go b/vendor/github.com/containers/buildah/chroot/selinux_unsupported.go
index 1c6f48912..41d2b86be 100644
--- a/vendor/github.com/containers/buildah/chroot/selinux_unsupported.go
+++ b/vendor/github.com/containers/buildah/chroot/selinux_unsupported.go
@@ -1,4 +1,4 @@
-// +build !linux !selinux
+// +build !linux
package chroot
diff --git a/vendor/github.com/containers/buildah/go.mod b/vendor/github.com/containers/buildah/go.mod
index ea9a956be..b5e2bc595 100644
--- a/vendor/github.com/containers/buildah/go.mod
+++ b/vendor/github.com/containers/buildah/go.mod
@@ -5,8 +5,8 @@ go 1.12
require (
github.com/containerd/containerd v1.4.1 // indirect
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784
- github.com/containers/common v0.31.0
- github.com/containers/image/v5 v5.8.1
+ github.com/containers/common v0.31.1
+ github.com/containers/image/v5 v5.9.0
github.com/containers/ocicrypt v1.0.3
github.com/containers/storage v1.24.3
github.com/docker/distribution v2.7.1+incompatible
@@ -27,7 +27,7 @@ require (
github.com/opencontainers/runc v1.0.0-rc91
github.com/opencontainers/runtime-spec v1.0.3-0.20200710190001-3e4195d92445
github.com/opencontainers/runtime-tools v0.9.0
- github.com/opencontainers/selinux v1.6.0
+ github.com/opencontainers/selinux v1.8.0
github.com/openshift/imagebuilder v1.1.8
github.com/pkg/errors v0.9.1
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf
diff --git a/vendor/github.com/containers/buildah/go.sum b/vendor/github.com/containers/buildah/go.sum
index c2082c5ef..c6c6f3c42 100644
--- a/vendor/github.com/containers/buildah/go.sum
+++ b/vendor/github.com/containers/buildah/go.sum
@@ -73,17 +73,15 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784 h1:rqUVLD8I859xRgUx/WMC3v7QAFqbLKZbs+0kqYboRJc=
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containers/common v0.31.0 h1:SRnjfoqbjfaojpY9YJq9JBPEslwB5hoXJbaE+5zMFwM=
-github.com/containers/common v0.31.0/go.mod h1:yT4GTUHsKRmpaDb+mecXRnIMre7W3ZgwXqaYMywXlaA=
-github.com/containers/image/v5 v5.8.1 h1:aHW8a/Kd0dTJ7PTL/fc6y12sJqHxWgqilu+XyHfjD8Q=
-github.com/containers/image/v5 v5.8.1/go.mod h1:blOEFd/iFdeyh891ByhCVUc+xAcaI3gBegXECwz9UbQ=
+github.com/containers/common v0.31.1 h1:oBINnZpYZ2u90HPMnVCXOhm/TsTaTB7wU/56l05hq44=
+github.com/containers/common v0.31.1/go.mod h1:Fehe82hQfJQvDspnRrV9rcdAWG3IalNHEt0F6QWNBHQ=
+github.com/containers/image/v5 v5.9.0 h1:dRmUtcluQcmasNo3DpnRoZjfU0rOu1qZeL6wlDJr10Q=
+github.com/containers/image/v5 v5.9.0/go.mod h1:blOEFd/iFdeyh891ByhCVUc+xAcaI3gBegXECwz9UbQ=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6GzVe1c=
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
github.com/containers/storage v1.23.7/go.mod h1:cUT2zHjtx+WlVri30obWmM2gpqpi8jfPsmIzP1TVpEI=
-github.com/containers/storage v1.24.1 h1:1+f8fy6ly35c8SLet5jzZ8t0WJJs5+xSpfMAYw0R3kc=
-github.com/containers/storage v1.24.1/go.mod h1:0xJL06Dmd+ZYXIUdnBUPN0JnhHGgwMkLvnnAonJfWJU=
github.com/containers/storage v1.24.3 h1:8UB4S62l4hrU6Yw3dbsLCJtLg7Ofo39IN2HdckBIX4E=
github.com/containers/storage v1.24.3/go.mod h1:0xJL06Dmd+ZYXIUdnBUPN0JnhHGgwMkLvnnAonJfWJU=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -303,8 +301,6 @@ github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
-github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U=
github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -327,6 +323,8 @@ github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pK
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/opencontainers/selinux v1.6.0 h1:+bIAS/Za3q5FTwWym4fTB0vObnfCf3G/NC7K6Jx62mY=
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
+github.com/opencontainers/selinux v1.8.0 h1:+77ba4ar4jsCbL1GLbFL8fFM57w6suPfSS9PDLDY7KM=
+github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/openshift/imagebuilder v1.1.8 h1:gjiIl8pbNj0eC4XWvFJHATdDvYm64p9/pLDLQWoLZPA=
github.com/openshift/imagebuilder v1.1.8/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
@@ -418,6 +416,8 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7Zo
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
+github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
+github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -484,8 +484,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go
index 1ec21e786..a7b0f6eaa 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/build.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/build.go
@@ -187,6 +187,9 @@ type BuildOptions struct {
LogRusage bool
// Excludes is a list of excludes to be used instead of the .dockerignore file.
Excludes []string
+ // From is the image name to use to replace the value specified in the first
+ // FROM instruction in the Containerfile
+ From string
}
// BuildDockerfiles parses a set of one or more Dockerfiles (which may be
diff --git a/vendor/github.com/containers/buildah/imagebuildah/executor.go b/vendor/github.com/containers/buildah/imagebuildah/executor.go
index 3c41ec1d2..a72e24eea 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/executor.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/executor.go
@@ -114,6 +114,7 @@ type Executor struct {
logRusage bool
imageInfoLock sync.Mutex
imageInfoCache map[string]imageTypeAndHistoryAndDiffIDs
+ fromOverride string
}
type imageTypeAndHistoryAndDiffIDs struct {
@@ -229,6 +230,7 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
jobs: jobs,
logRusage: options.LogRusage,
imageInfoCache: make(map[string]imageTypeAndHistoryAndDiffIDs),
+ fromOverride: options.From,
}
if exec.err == nil {
exec.err = os.Stderr
@@ -245,6 +247,7 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
fmt.Fprintf(exec.out, prefix+format+suffix, args...)
}
}
+
for arg := range options.Args {
if _, isBuiltIn := builtinAllowedBuildArgs[arg]; !isBuiltIn {
exec.unusedArgs[arg] = struct{}{}
@@ -522,6 +525,12 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
switch strings.ToUpper(child.Value) { // first token - instruction
case "FROM":
if child.Next != nil { // second token on this line
+ // If we have a fromOverride, replace the value of
+ // image name for the first FROM in the Containerfile.
+ if b.fromOverride != "" {
+ child.Next.Value = b.fromOverride
+ b.fromOverride = ""
+ }
base := child.Next.Value
if base != "scratch" {
// TODO: this didn't undergo variable and arg
diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go
index 1e2db58c4..ded553ac2 100644
--- a/vendor/github.com/containers/buildah/pkg/cli/common.go
+++ b/vendor/github.com/containers/buildah/pkg/cli/common.go
@@ -63,6 +63,7 @@ type BudResults struct {
IgnoreFile string
File []string
Format string
+ From string
Iidfile string
Label []string
Logfile string
@@ -81,6 +82,7 @@ type BudResults struct {
SignaturePolicy string
SignBy string
Squash bool
+ Stdin bool
Tag []string
Target string
TLSVerify bool
@@ -187,6 +189,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.StringVar(&flags.Creds, "creds", "", "use `[username[:password]]` for accessing the registry")
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.StringVar(&flags.From, "from", "", "image name used to replace the value in the first FROM instruction in the Containerfile")
fs.StringVar(&flags.IgnoreFile, "ignorefile", "", "path to an alternate .dockerignore file")
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.")
@@ -215,6 +218,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
panic(fmt.Sprintf("error marking the signature-policy flag as hidden: %v", err))
}
fs.BoolVar(&flags.Squash, "squash", false, "squash newly built layers into a single new layer")
+ fs.BoolVar(&flags.Stdin, "stdin", false, "pass stdin into containers")
fs.StringArrayVarP(&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.Int64Var(&flags.Timestamp, "timestamp", 0, "set created timestamp to the specified epoch seconds to allow for deterministic builds, defaults to current time")
@@ -233,6 +237,7 @@ func GetBudFlagsCompletions() commonComp.FlagCompletions {
flagCompletion["cert-dir"] = commonComp.AutocompleteDefault
flagCompletion["creds"] = commonComp.AutocompleteNone
flagCompletion["file"] = commonComp.AutocompleteDefault
+ flagCompletion["from"] = commonComp.AutocompleteDefault
flagCompletion["format"] = commonComp.AutocompleteNone
flagCompletion["ignorefile"] = commonComp.AutocompleteDefault
flagCompletion["iidfile"] = commonComp.AutocompleteDefault
diff --git a/vendor/github.com/containers/buildah/selinux.go b/vendor/github.com/containers/buildah/selinux.go
index fea863165..00903203e 100644
--- a/vendor/github.com/containers/buildah/selinux.go
+++ b/vendor/github.com/containers/buildah/selinux.go
@@ -1,4 +1,4 @@
-// +build selinux,linux
+// +build linux
package buildah
diff --git a/vendor/github.com/containers/buildah/selinux_unsupported.go b/vendor/github.com/containers/buildah/selinux_unsupported.go
index fb9213e29..264614837 100644
--- a/vendor/github.com/containers/buildah/selinux_unsupported.go
+++ b/vendor/github.com/containers/buildah/selinux_unsupported.go
@@ -1,4 +1,4 @@
-// +build !selinux !linux
+// +build !linux
package buildah
diff --git a/vendor/github.com/containers/common/pkg/auth/auth.go b/vendor/github.com/containers/common/pkg/auth/auth.go
index 21b988187..8daaf4c08 100644
--- a/vendor/github.com/containers/common/pkg/auth/auth.go
+++ b/vendor/github.com/containers/common/pkg/auth/auth.go
@@ -16,10 +16,17 @@ import (
"golang.org/x/crypto/ssh/terminal"
)
-// GetDefaultAuthFile returns env value REGISTRY_AUTH_FILE as default --authfile path
-// used in multiple --authfile flag definitions
+// GetDefaultAuthFile returns env value REGISTRY_AUTH_FILE as default
+// --authfile path used in multiple --authfile flag definitions
+// Will fail over to DOCKER_CONFIG if REGISTRY_AUTH_FILE environment is not set
func GetDefaultAuthFile() string {
- return os.Getenv("REGISTRY_AUTH_FILE")
+ authfile := os.Getenv("REGISTRY_AUTH_FILE")
+ if authfile == "" {
+ if authfile, ok := os.LookupEnv("DOCKER_CONFIG"); ok {
+ logrus.Infof("Using DOCKER_CONFIG environment variable for authfile path %s", authfile)
+ }
+ }
+ return authfile
}
// CheckAuthFile validates filepath given by --authfile
diff --git a/vendor/github.com/containers/common/pkg/completion/completion.go b/vendor/github.com/containers/common/pkg/completion/completion.go
index 07451e992..90fe2f111 100644
--- a/vendor/github.com/containers/common/pkg/completion/completion.go
+++ b/vendor/github.com/containers/common/pkg/completion/completion.go
@@ -91,3 +91,51 @@ func AutocompleteSubgidName(cmd *cobra.Command, args []string, toComplete string
func AutocompleteSubuidName(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return autocompleteSubIDName("/etc/subuid")
}
+
+// AutocompleteArch - Autocomplete platform supported by container engines
+func AutocompletePlatform(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+ completions := []string{
+ "linux/386",
+ "linux/amd64",
+ "linux/arm",
+ "linux/arm64",
+ "linux/ppc64",
+ "linux/ppc64le",
+ "linux/mips",
+ "linux/mipsle",
+ "linux/mips64",
+ "linux/mips64le",
+ "linux/riscv64",
+ "linux/s390x",
+ "windows/386",
+ "windows/amd64",
+ "windows/arm",
+ }
+ return completions, cobra.ShellCompDirectiveNoFileComp
+}
+
+// AutocompleteArch - Autocomplete architectures supported by container engines
+func AutocompleteArch(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+ completions := []string{
+ "386",
+ "amd64",
+ "arm",
+ "arm64",
+ "ppc64",
+ "ppc64le",
+ "mips",
+ "mipsle",
+ "mips64",
+ "mips64le",
+ "riscv64",
+ "s390x",
+ }
+
+ return completions, cobra.ShellCompDirectiveNoFileComp
+}
+
+// AutocompleteOS - Autocomplete OS supported by container engines
+func AutocompleteOS(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+ completions := []string{"linux", "windows"}
+ return completions, cobra.ShellCompDirectiveNoFileComp
+}
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index ea08ab6ad..16817f7b3 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -746,13 +746,20 @@ func (c *Config) FindConmon() (string, error) {
}
// GetDefaultEnv returns the environment variables for the container.
-// It will checn the HTTPProxy and HostEnv booleans and add the appropriate
+// It will check the HTTPProxy and HostEnv booleans and add the appropriate
// environment variables to the container.
func (c *Config) GetDefaultEnv() []string {
+ return c.GetDefaultEnvEx(c.Containers.EnvHost, c.Containers.HTTPProxy)
+}
+
+// GetDefaultEnvEx returns the environment variables for the container.
+// It will check the HTTPProxy and HostEnv boolean parameters and return the appropriate
+// environment variables for the container.
+func (c *Config) GetDefaultEnvEx(envHost, httpProxy bool) []string {
var env []string
- if c.Containers.EnvHost {
+ if envHost {
env = append(env, os.Environ()...)
- } else if c.Containers.HTTPProxy {
+ } else if httpProxy {
proxy := []string{"http_proxy", "https_proxy", "ftp_proxy", "no_proxy", "HTTP_PROXY", "HTTPS_PROXY", "FTP_PROXY", "NO_PROXY"}
for _, p := range proxy {
if val, ok := os.LookupEnv(p); ok {
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 6b7aee987..2e26fb7b8 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -184,7 +184,7 @@ func DefaultConfig() (*Config, error) {
"TERM=xterm",
},
EnvHost: false,
- HTTPProxy: false,
+ HTTPProxy: true,
Init: false,
InitPath: "",
IPCNS: "private",
diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go
index f6ecab0c0..a06c7c08d 100644
--- a/vendor/github.com/containers/common/pkg/retry/retry.go
+++ b/vendor/github.com/containers/common/pkg/retry/retry.go
@@ -30,7 +30,7 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions
if retryOptions.Delay != 0 {
delay = retryOptions.Delay
}
- logrus.Infof("Warning: failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err)
+ logrus.Warnf("failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err)
select {
case <-time.After(delay):
break
@@ -69,7 +69,7 @@ func isRetryable(err error) bool {
}
return isRetryable(e.Err)
case syscall.Errno:
- return e != syscall.ECONNREFUSED
+ return shouldRestart(e)
case errcode.Errors:
// if this error is a group of errors, process them all in turn
for i := range e {
@@ -93,3 +93,11 @@ func isRetryable(err error) bool {
return false
}
+
+func shouldRestart(e error) bool {
+ switch e {
+ case syscall.ECONNREFUSED, syscall.EINTR, syscall.EAGAIN, syscall.EBUSY, syscall.ENETDOWN, syscall.ENETUNREACH, syscall.ENETRESET, syscall.ECONNABORTED, syscall.ECONNRESET, syscall.ETIMEDOUT, syscall.EHOSTDOWN, syscall.EHOSTUNREACH:
+ return true
+ }
+ return shouldRestartPlatform(e)
+}
diff --git a/vendor/github.com/containers/common/pkg/retry/retry_linux.go b/vendor/github.com/containers/common/pkg/retry/retry_linux.go
new file mode 100644
index 000000000..9da0ba287
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/retry/retry_linux.go
@@ -0,0 +1,9 @@
+package retry
+
+import (
+ "syscall"
+)
+
+func shouldRestartPlatform(e error) bool {
+ return e == syscall.ERESTART
+}
diff --git a/vendor/github.com/containers/common/pkg/retry/retry_unsupported.go b/vendor/github.com/containers/common/pkg/retry/retry_unsupported.go
new file mode 100644
index 000000000..cf55b2a94
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/retry/retry_unsupported.go
@@ -0,0 +1,7 @@
+// +build !linux
+
+package retry
+
+func shouldRestartPlatform(e error) bool {
+ return false
+}
diff --git a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go
index a127571b5..5c4427318 100644
--- a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go
+++ b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go
@@ -378,7 +378,6 @@ func DefaultProfile() *Seccomp {
"utimensat_time64",
"utimes",
"vfork",
- "vmsplice",
"wait4",
"waitid",
"waitpid",
diff --git a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json
index 8fb509345..d6f3f4938 100644
--- a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json
+++ b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json
@@ -378,7 +378,6 @@
"utimensat_time64",
"utimes",
"vfork",
- "vmsplice",
"wait4",
"waitid",
"waitpid",
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index 4366848ea..b696294ac 100644
--- a/vendor/github.com/containers/common/version/version.go
+++ b/vendor/github.com/containers/common/version/version.go
@@ -1,4 +1,4 @@
package version
// Version is the version of the build.
-const Version = "0.31.2"
+const Version = "0.33.0"
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 2f4320f67..6521720b4 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.24.4
+1.24.5
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index c1895c364..6e5a76cf3 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -761,19 +761,29 @@ func (d *Driver) optsAppendMappings(opts string, uidMaps, gidMaps []idtools.IDMa
}
if uidMaps != nil {
var uids, gids bytes.Buffer
- for _, i := range uidMaps {
- if uids.Len() > 0 {
- uids.WriteString(":")
+ if len(uidMaps) == 1 && uidMaps[0].Size == 1 {
+ uids.WriteString(fmt.Sprintf("squash_to_uid=%d", uidMaps[0].HostID))
+ } else {
+ uids.WriteString("uidmapping=")
+ for _, i := range uidMaps {
+ if uids.Len() > 0 {
+ uids.WriteString(":")
+ }
+ uids.WriteString(fmt.Sprintf("%d:%d:%d", i.ContainerID, i.HostID, i.Size))
}
- uids.WriteString(fmt.Sprintf("%d:%d:%d", i.ContainerID, i.HostID, i.Size))
}
- for _, i := range gidMaps {
- if gids.Len() > 0 {
- gids.WriteString(":")
+ if len(gidMaps) == 1 && gidMaps[0].Size == 1 {
+ gids.WriteString(fmt.Sprintf("squash_to_gid=%d", gidMaps[0].HostID))
+ } else {
+ gids.WriteString("gidmapping=")
+ for _, i := range gidMaps {
+ if gids.Len() > 0 {
+ gids.WriteString(":")
+ }
+ gids.WriteString(fmt.Sprintf("%d:%d:%d", i.ContainerID, i.HostID, i.Size))
}
- gids.WriteString(fmt.Sprintf("%d:%d:%d", i.ContainerID, i.HostID, i.Size))
}
- return fmt.Sprintf("%s,uidmapping=%s,gidmapping=%s", opts, uids.String(), gids.String())
+ return fmt.Sprintf("%s,%s,%s", opts, uids.String(), gids.String())
}
return opts
}
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index b19b4a7c4..8af8ceddb 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -8,7 +8,7 @@ require (
github.com/Microsoft/hcsshim v0.8.14
github.com/docker/go-units v0.4.0
github.com/hashicorp/go-multierror v1.1.0
- github.com/klauspost/compress v1.11.4
+ github.com/klauspost/compress v1.11.5
github.com/klauspost/pgzip v1.2.5
github.com/mattn/go-shellwords v1.0.10
github.com/mistifyio/go-zfs v2.1.1+incompatible
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index a7be24d40..c786686bc 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -58,8 +58,8 @@ github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU=
-github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.5 h1:xNCE0uE6yvTPRS+0wGNMHPo3NIpwnk6aluQZ6R6kRcc=
+github.com/klauspost/compress v1.11.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
diff --git a/vendor/github.com/containers/storage/pkg/idtools/idtools.go b/vendor/github.com/containers/storage/pkg/idtools/idtools.go
index 0958c0c5d..0cd386929 100644
--- a/vendor/github.com/containers/storage/pkg/idtools/idtools.go
+++ b/vendor/github.com/containers/storage/pkg/idtools/idtools.go
@@ -77,13 +77,23 @@ func MkdirAllAndChownNew(path string, mode os.FileMode, ids IDPair) error {
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
// If the maps are empty, then the root uid/gid will default to "real" 0/0
func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
- uid, err := toHost(0, uidMap)
- if err != nil {
- return -1, -1, err
+ var uid, gid int
+ var err error
+ if len(uidMap) == 1 && uidMap[0].Size == 1 {
+ uid = uidMap[0].HostID
+ } else {
+ uid, err = toHost(0, uidMap)
+ if err != nil {
+ return -1, -1, err
+ }
}
- gid, err := toHost(0, gidMap)
- if err != nil {
- return -1, -1, err
+ if len(gidMap) == 1 && gidMap[0].Size == 1 {
+ gid = gidMap[0].HostID
+ } else {
+ gid, err = toHost(0, gidMap)
+ if err != nil {
+ return -1, -1, err
+ }
}
return uid, gid, nil
}
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 0b53d81ce..fa595355d 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -3522,10 +3522,11 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
fmt.Printf("Failed to parse %s %v\n", configFile, err.Error())
return
}
+ if config.Storage.Driver != "" {
+ storeOptions.GraphDriverName = config.Storage.Driver
+ }
if os.Getenv("STORAGE_DRIVER") != "" {
config.Storage.Driver = os.Getenv("STORAGE_DRIVER")
- }
- if config.Storage.Driver != "" {
storeOptions.GraphDriverName = config.Storage.Driver
}
if storeOptions.GraphDriverName == "" {
diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go
index bd6c4feb1..ecfcf45e3 100644
--- a/vendor/github.com/containers/storage/utils.go
+++ b/vendor/github.com/containers/storage/utils.go
@@ -211,18 +211,27 @@ func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOpti
} else {
opts.GraphRoot = filepath.Join(dataDir, "containers", "storage")
}
- if path, err := exec.LookPath("fuse-overlayfs"); err == nil {
- opts.GraphDriverName = "overlay"
- opts.GraphDriverOptions = []string{fmt.Sprintf("overlay.mount_program=%s", path)}
- for _, o := range systemOpts.GraphDriverOptions {
- if strings.Contains(o, "ignore_chown_errors") {
- opts.GraphDriverOptions = append(opts.GraphDriverOptions, o)
- break
+ opts.GraphDriverName = os.Getenv("STORAGE_DRIVER")
+ if opts.GraphDriverName == "" || opts.GraphDriverName == "overlay" {
+ if path, err := exec.LookPath("fuse-overlayfs"); err == nil {
+ opts.GraphDriverName = "overlay"
+ opts.GraphDriverOptions = []string{fmt.Sprintf("overlay.mount_program=%s", path)}
+ for _, o := range systemOpts.GraphDriverOptions {
+ if strings.Contains(o, "ignore_chown_errors") {
+ opts.GraphDriverOptions = append(opts.GraphDriverOptions, o)
+ break
+ }
}
}
- } else {
+ }
+ if opts.GraphDriverName == "" {
opts.GraphDriverName = "vfs"
}
+
+ if os.Getenv("STORAGE_OPTS") != "" {
+ opts.GraphDriverOptions = append(opts.GraphDriverOptions, strings.Split(os.Getenv("STORAGE_OPTS"), ",")...)
+ }
+
return opts, nil
}
diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go
index daf3639c1..60d26bb50 100644
--- a/vendor/github.com/google/uuid/uuid.go
+++ b/vendor/github.com/google/uuid/uuid.go
@@ -37,7 +37,7 @@ var rander = rand.Reader // random function
type invalidLengthError struct{ len int }
-func (err *invalidLengthError) Error() string {
+func (err invalidLengthError) Error() string {
return fmt.Sprintf("invalid UUID length: %d", err.len)
}
@@ -74,7 +74,7 @@ func Parse(s string) (UUID, error) {
}
return uuid, nil
default:
- return uuid, &invalidLengthError{len(s)}
+ return uuid, invalidLengthError{len(s)}
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
@@ -118,7 +118,7 @@ func ParseBytes(b []byte) (UUID, error) {
}
return uuid, nil
default:
- return uuid, &invalidLengthError{len(b)}
+ return uuid, invalidLengthError{len(b)}
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go
index cdda0de58..62fd37324 100644
--- a/vendor/github.com/klauspost/compress/zstd/decoder.go
+++ b/vendor/github.com/klauspost/compress/zstd/decoder.go
@@ -85,6 +85,10 @@ func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) {
d.current.output = make(chan decodeOutput, d.o.concurrent)
d.current.flushed = true
+ if r == nil {
+ d.current.err = ErrDecoderNilInput
+ }
+
// Transfer option dicts.
d.dicts = make(map[uint32]dict, len(d.o.dicts))
for _, dc := range d.o.dicts {
@@ -111,7 +115,7 @@ func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) {
// When the stream is done, io.EOF will be returned.
func (d *Decoder) Read(p []byte) (int, error) {
if d.stream == nil {
- return 0, errors.New("no input has been initialized")
+ return 0, ErrDecoderNilInput
}
var n int
for {
@@ -152,12 +156,20 @@ func (d *Decoder) Read(p []byte) (int, error) {
// Reset will reset the decoder the supplied stream after the current has finished processing.
// Note that this functionality cannot be used after Close has been called.
+// Reset can be called with a nil reader to release references to the previous reader.
+// After being called with a nil reader, no other operations than Reset or DecodeAll or Close
+// should be used.
func (d *Decoder) Reset(r io.Reader) error {
if d.current.err == ErrDecoderClosed {
return d.current.err
}
+
+ d.drainOutput()
+
if r == nil {
- return errors.New("nil Reader sent as input")
+ d.current.err = ErrDecoderNilInput
+ d.current.flushed = true
+ return nil
}
if d.stream == nil {
@@ -166,8 +178,6 @@ func (d *Decoder) Reset(r io.Reader) error {
go d.startStreamDecoder(d.stream)
}
- d.drainOutput()
-
// If bytes buffer and < 1MB, do sync decoding anyway.
if bb, ok := r.(*bytes.Buffer); ok && bb.Len() < 1<<20 {
if debug {
@@ -249,7 +259,7 @@ func (d *Decoder) drainOutput() {
// Any error encountered during the write is also returned.
func (d *Decoder) WriteTo(w io.Writer) (int64, error) {
if d.stream == nil {
- return 0, errors.New("no input has been initialized")
+ return 0, ErrDecoderNilInput
}
var n int64
for {
diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec.go b/vendor/github.com/klauspost/compress/zstd/seqdec.go
index b5c8ef133..1dd39e63b 100644
--- a/vendor/github.com/klauspost/compress/zstd/seqdec.go
+++ b/vendor/github.com/klauspost/compress/zstd/seqdec.go
@@ -181,11 +181,18 @@ func (s *sequenceDecs) decode(seqs int, br *bitReader, hist []byte) error {
return fmt.Errorf("output (%d) bigger than max block size", size)
}
if size > cap(s.out) {
- // Not enough size, will be extremely rarely triggered,
+ // Not enough size, which can happen under high volume block streaming conditions
// but could be if destination slice is too small for sync operations.
- // We add maxBlockSize to the capacity.
- s.out = append(s.out, make([]byte, maxBlockSize)...)
- s.out = s.out[:len(s.out)-maxBlockSize]
+ // over-allocating here can create a large amount of GC pressure so we try to keep
+ // it as contained as possible
+ used := len(s.out) - startSize
+ addBytes := 256 + ll + ml + used>>2
+ // Clamp to max block size.
+ if used+addBytes > maxBlockSize {
+ addBytes = maxBlockSize - used
+ }
+ s.out = append(s.out, make([]byte, addBytes)...)
+ s.out = s.out[:len(s.out)-addBytes]
}
if ml > maxMatchLen {
return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go
index 0807719c8..0c761dd62 100644
--- a/vendor/github.com/klauspost/compress/zstd/zstd.go
+++ b/vendor/github.com/klauspost/compress/zstd/zstd.go
@@ -73,6 +73,10 @@ var (
// ErrDecoderClosed will be returned if the Decoder was used after
// Close has been called.
ErrDecoderClosed = errors.New("decoder used after Close")
+
+ // ErrDecoderNilInput is returned when a nil Reader was provided
+ // and an operation other than Reset/DecodeAll/Close was attempted.
+ ErrDecoderNilInput = errors.New("nil input provided as reader")
)
func println(a ...interface{}) {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 39771fbe8..e15b16188 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -70,7 +70,7 @@ github.com/containernetworking/plugins/pkg/utils/hwaddr
github.com/containernetworking/plugins/pkg/utils/sysctl
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
-# github.com/containers/buildah v1.18.1-0.20201217112226-67470615779c
+# github.com/containers/buildah v1.18.1-0.20201222143428-b9fdee076426
github.com/containers/buildah
github.com/containers/buildah/bind
github.com/containers/buildah/chroot
@@ -89,7 +89,7 @@ github.com/containers/buildah/pkg/parse
github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/supplemented
github.com/containers/buildah/util
-# github.com/containers/common v0.31.2
+# github.com/containers/common v0.33.0
github.com/containers/common/pkg/apparmor
github.com/containers/common/pkg/apparmor/internal/supported
github.com/containers/common/pkg/auth
@@ -171,7 +171,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.24.4
+# github.com/containers/storage v1.24.5
github.com/containers/storage
github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs
@@ -318,7 +318,7 @@ github.com/golang/protobuf/ptypes/timestamp
github.com/google/gofuzz
# github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/google/shlex
-# github.com/google/uuid v1.1.3
+# github.com/google/uuid v1.1.4
github.com/google/uuid
# github.com/gorilla/mux v1.8.0
github.com/gorilla/mux
@@ -347,7 +347,7 @@ github.com/json-iterator/go
# github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a
github.com/juju/ansiterm
github.com/juju/ansiterm/tabwriter
-# github.com/klauspost/compress v1.11.4
+# github.com/klauspost/compress v1.11.5
github.com/klauspost/compress/flate
github.com/klauspost/compress/fse
github.com/klauspost/compress/huff0