From b61701acb38d64a3d2622ebb86ad794435e94e54 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 9 Jun 2021 13:55:03 +0200 Subject: [PATCH 01/21] container: ignore named hierarchies when looking up the container cgroup, ignore named hierarchies since containers running systemd as payload will create a sub-cgroup and move themselves there. Closes: https://github.com/containers/podman/issues/10602 Signed-off-by: Giuseppe Scrivano --- libpod/container.go | 10 ++++++++++ test/e2e/systemd_test.go | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/libpod/container.go b/libpod/container.go index bad91d54f1..e14051f804 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -946,6 +946,12 @@ func (c *Container) cGroupPath() (string, error) { // is the libpod-specific one we're looking for. // // See #8397 on the need for the longest-path look up. + // + // And another workaround for containers running systemd as the payload. + // containers running systemd moves themselves into a child subgroup of + // the named systemd cgroup hierarchy. Ignore any named cgroups during + // the lookup. + // See #10602 for more details. procPath := fmt.Sprintf("/proc/%d/cgroup", c.state.PID) lines, err := ioutil.ReadFile(procPath) if err != nil { @@ -961,6 +967,10 @@ func (c *Container) cGroupPath() (string, error) { logrus.Debugf("Error parsing cgroup: expected 3 fields but got %d: %s", len(fields), procPath) continue } + // Ignore named cgroups like name=systemd. + if bytes.Contains(fields[1], []byte("=")) { + continue + } path := string(fields[2]) if len(path) > len(cgroupPath) { cgroupPath = path diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index b132750b04..8dc14d5f79 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/containers/podman/v3/pkg/rootless" . "github.com/containers/podman/v3/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -115,6 +116,12 @@ WantedBy=multi-user.target conData := result.InspectContainerToJSON() Expect(len(conData)).To(Equal(1)) Expect(conData[0].Config.SystemdMode).To(BeTrue()) + + if CGROUPSV2 || !rootless.IsRootless() { + stats := podmanTest.Podman([]string{"stats", "--no-stream", ctrName}) + stats.WaitWithDefaultTimeout() + Expect(stats.ExitCode()).To(Equal(0)) + } }) It("podman create container with systemd entrypoint triggers systemd mode", func() { From c85b6b3fe1b17716492d0fd6f2e13331a6ed8890 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 10 Jun 2021 12:27:09 +0000 Subject: [PATCH 02/21] Fix pre-checkpointing Unfortunately --pre-checkpointing never worked as intended and recent changes to runc have shown that it is broken. To create a pre-checkpoint CRIU expects the paths between the pre-checkpoints to be a relative path. If having a previous checkpoint it needs the be referenced like this: --prev-images-dir ../parent Unfortunately Podman was giving runc (and CRIU) an absolute path. Unfortunately, again, until March 2021 CRIU silently ignored if the path was not relative and switch back to normal checkpointing. This has been now fixed in CRIU and runc and running pre-checkpoint with the latest runc fails, because runc already sees that the path is absolute and returns an error. This commit fixes this by giving runc a relative path. This commit also fixes a second pre-checkpointing error which was just recently introduced. So summarizing: pre-checkpointing never worked correctly because CRIU ignored wrong parameters and recent changes broke it even more. Now both errors should be fixed. [NO TESTS NEEDED] Signed-off-by: Adrian Reber Signed-off-by: Adrian Reber --- libpod/container_internal.go | 3 ++- libpod/container_internal_linux.go | 5 +++-- libpod/oci_conmon_linux.go | 6 +++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 53b85a466e..af7e974714 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -41,6 +41,7 @@ const ( // name of the directory holding the artifacts artifactsDir = "artifacts" execDirPermission = 0755 + preCheckpointDir = "pre-checkpoint" ) // rootFsSize gets the size of the container's root filesystem @@ -140,7 +141,7 @@ func (c *Container) CheckpointPath() string { // PreCheckpointPath returns the path to the directory containing the pre-checkpoint-images func (c *Container) PreCheckPointPath() string { - return filepath.Join(c.bundlePath(), "pre-checkpoint") + return filepath.Join(c.bundlePath(), preCheckpointDir) } // AttachSocketPath retrieves the path of the container's attach socket diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index df9e03e78f..bf235e42c8 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -907,14 +907,15 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { includeFiles := []string{ "artifacts", "ctr.log", - metadata.CheckpointDirectory, metadata.ConfigDumpFile, metadata.SpecDumpFile, metadata.NetworkStatusFile, } if options.PreCheckPoint { - includeFiles[0] = "pre-checkpoint" + includeFiles = append(includeFiles, preCheckpointDir) + } else { + includeFiles = append(includeFiles, metadata.CheckpointDirectory) } // Get root file-system changes included in the checkpoint archive var addToTarFiles []string diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 3da49b85f8..2914bd1a19 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -787,7 +787,11 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container args = append(args, "--pre-dump") } if !options.PreCheckPoint && options.WithPrevious { - args = append(args, "--parent-path", ctr.PreCheckPointPath()) + args = append( + args, + "--parent-path", + filepath.Join("..", preCheckpointDir), + ) } runtimeDir, err := util.GetRuntimeDir() if err != nil { From 80362b34c4d23fe8a46136422572469285cb80b1 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 10 Jun 2021 10:00:21 +0200 Subject: [PATCH 03/21] Fix build tags for pkg/machine... Podman machine is only intended for amd64 and arm64 architectures, set the correct buildtags so that the `pkg/machine`, `pkg/machine/qemu` and `pkg/machine/libvirt` packages compile correctly. [NO TESTS NEEDED] Fixes #10625 Signed-off-by: Paul Holzinger --- pkg/machine/config.go | 2 ++ pkg/machine/connection.go | 2 ++ pkg/machine/fcos.go | 2 ++ pkg/machine/ignition.go | 2 ++ pkg/machine/ignition_schema.go | 2 ++ pkg/machine/keys.go | 2 ++ pkg/machine/libvirt/config.go | 2 ++ pkg/machine/libvirt/machine.go | 2 ++ pkg/machine/libvirt/machine_unsupported.go | 3 +++ pkg/machine/machine_unsupported.go | 3 +++ pkg/machine/pull.go | 2 ++ pkg/machine/qemu/config.go | 2 ++ pkg/machine/qemu/machine.go | 2 ++ pkg/machine/qemu/machine_unsupported.go | 3 +++ 14 files changed, 31 insertions(+) create mode 100644 pkg/machine/libvirt/machine_unsupported.go create mode 100644 pkg/machine/machine_unsupported.go create mode 100644 pkg/machine/qemu/machine_unsupported.go diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 652229963d..f6dd1d8d47 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/connection.go b/pkg/machine/connection.go index e3985d8ac3..3edcbd10e0 100644 --- a/pkg/machine/connection.go +++ b/pkg/machine/connection.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go index 32f943c870..11936aee77 100644 --- a/pkg/machine/fcos.go +++ b/pkg/machine/fcos.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index 00068a1368..cdb50bb397 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/ignition_schema.go b/pkg/machine/ignition_schema.go index 9dbd90ba4a..6ac8af826f 100644 --- a/pkg/machine/ignition_schema.go +++ b/pkg/machine/ignition_schema.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine /* diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go index 907e28f550..81ec44ea85 100644 --- a/pkg/machine/keys.go +++ b/pkg/machine/keys.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/libvirt/config.go b/pkg/machine/libvirt/config.go index 903f15fbcc..1ce5ab1549 100644 --- a/pkg/machine/libvirt/config.go +++ b/pkg/machine/libvirt/config.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package libvirt type MachineVM struct { diff --git a/pkg/machine/libvirt/machine.go b/pkg/machine/libvirt/machine.go index c38f638537..e1aa1569b0 100644 --- a/pkg/machine/libvirt/machine.go +++ b/pkg/machine/libvirt/machine.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package libvirt import "github.com/containers/podman/v3/pkg/machine" diff --git a/pkg/machine/libvirt/machine_unsupported.go b/pkg/machine/libvirt/machine_unsupported.go new file mode 100644 index 0000000000..8b54440fe8 --- /dev/null +++ b/pkg/machine/libvirt/machine_unsupported.go @@ -0,0 +1,3 @@ +// +build !amd64 amd64,windows + +package libvirt diff --git a/pkg/machine/machine_unsupported.go b/pkg/machine/machine_unsupported.go new file mode 100644 index 0000000000..9309d16bcb --- /dev/null +++ b/pkg/machine/machine_unsupported.go @@ -0,0 +1,3 @@ +// +build !amd64 amd64,windows + +package machine diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go index 68bb551dc1..662896de51 100644 --- a/pkg/machine/pull.go +++ b/pkg/machine/pull.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index e4687914da..013f28960e 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package qemu import "time" diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 269a2a2da3..956f80fa32 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package qemu import ( diff --git a/pkg/machine/qemu/machine_unsupported.go b/pkg/machine/qemu/machine_unsupported.go new file mode 100644 index 0000000000..da06ac324c --- /dev/null +++ b/pkg/machine/qemu/machine_unsupported.go @@ -0,0 +1,3 @@ +// +build !amd64 amd64,windows + +package qemu From 6beae86f014ceb1ad2f0a33b626b7881bf17e419 Mon Sep 17 00:00:00 2001 From: Ed Santiago Date: Wed, 9 Jun 2021 10:04:11 -0600 Subject: [PATCH 04/21] System tests: deal with crun 0.20.1 crun 0.20.1 changed an error message that we relied on. Deal with it by accepting the old and new message. Also (unrelated): sneak in some doc fixes to get rid of nasty go-md2man warnings that have crept into man pages. Signed-off-by: Ed Santiago Signed-off-by: Matthew Heon --- docs/source/markdown/podman-network-create.1.md | 2 +- docs/source/markdown/podman-pod-create.1.md | 4 ++-- test/system/410-selinux.bats | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/source/markdown/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md index 3d5d980550..d110c4ceba 100644 --- a/docs/source/markdown/podman-network-create.1.md +++ b/docs/source/markdown/podman-network-create.1.md @@ -9,7 +9,7 @@ podman\-network-create - Create a Podman CNI network ## DESCRIPTION Create a CNI-network configuration for use with Podman. By default, Podman creates a bridge connection. A *Macvlan* connection can be created with the *-d macvlan* option. A parent device for macvlan can -be designated with the *-o parent=\* option. In the case of *Macvlan* connections, the +be designated with the *-o parent=``* option. In the case of *Macvlan* connections, the CNI *dhcp* plugin needs to be activated or the container image must have a DHCP client to interact with the host network's DHCP server. diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index 37eb098d1c..4b890a7afc 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -10,8 +10,8 @@ podman\-pod\-create - Create a new pod Creates an empty pod, or unit of multiple containers, and prepares it to have containers added to it. The pod id is printed to STDOUT. You can then use -**podman create --pod \ ...** to add containers to the pod, and -**podman pod start \** to start the pod. +**podman create --pod `` ...** to add containers to the pod, and +**podman pod start ``** to start the pod. ## OPTIONS diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index f8cee0e59e..4ef9c8b308 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -183,7 +183,10 @@ function check_label() { # runc and crun emit different diagnostics runtime=$(podman_runtime) case "$runtime" in - crun) expect="\`/proc/thread-self/attr/exec\`: OCI runtime error: unable to assign security attribute" ;; + # crun 0.20.1 changes the error message + # from /proc/thread-self/attr/exec`: .* unable to assign + # to /proc/self/attr/keycreate`: .* unable to process + crun) expect="\`/proc/.*\`: OCI runtime error: unable to \(assign\|process\) security attribute" ;; runc) expect="OCI runtime error: .*: failed to set /proc/self/attr/keycreate on procfs" ;; *) skip "Unknown runtime '$runtime'";; esac From 2afb5eeab672f6b10cda78f4d6bc152cf1e9a769 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 3 Jun 2021 11:00:04 -0400 Subject: [PATCH 05/21] podman-remote build should handle -f option properly podman-remote build has to handle multiple different locations for the Containerfile. Currently this works in local mode but not when using podman-remote. Fixes: https://github.com/containers/podman/issues/9871 Signed-off-by: Daniel J Walsh --- pkg/api/handlers/compat/images_build.go | 27 ++++++++++- pkg/bindings/images/build.go | 64 ++++++++++++++++--------- test/system/070-build.bats | 26 ++++++++++ 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 6ff5572916..50423fb96a 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -139,6 +139,31 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { addCaps = m } + // convert addcaps formats + containerFiles := []string{} + if _, found := r.URL.Query()["dockerfile"]; found { + var m = []string{} + if err := json.Unmarshal([]byte(query.Dockerfile), &m); err != nil { + utils.BadRequest(w, "dockerfile", query.Dockerfile, err) + return + } + containerFiles = m + } else { + containerFiles = []string{"Dockerfile"} + if utils.IsLibpodRequest(r) { + containerFiles = []string{"Containerfile"} + if _, err = os.Stat(filepath.Join(contextDirectory, "Containerfile")); err != nil { + if _, err1 := os.Stat(filepath.Join(contextDirectory, "Dockerfile")); err1 == nil { + containerFiles = []string{"Dockerfile"} + } else { + utils.BadRequest(w, "dockerfile", query.Dockerfile, err) + } + } + } else { + containerFiles = []string{"Dockerfile"} + } + } + addhosts := []string{} if _, found := r.URL.Query()["extrahosts"]; found { if err := json.Unmarshal([]byte(query.AddHosts), &addhosts); err != nil { @@ -470,7 +495,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { runCtx, cancel := context.WithCancel(context.Background()) go func() { defer cancel() - imageID, _, err = runtime.Build(r.Context(), buildOptions, query.Dockerfile) + imageID, _, err = runtime.Build(r.Context(), buildOptions, containerFiles...) if err == nil { success = true } else { diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 346d55c47f..c7d432b16c 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -282,10 +282,6 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO stdout = options.Out } - entries := make([]string, len(containerFiles)) - copy(entries, containerFiles) - entries = append(entries, options.ContextDirectory) - excludes := options.Excludes if len(excludes) == 0 { excludes, err = parseDockerignore(options.ContextDirectory) @@ -294,33 +290,57 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } } - tarfile, err := nTar(excludes, entries...) + contextDir, err := filepath.Abs(options.ContextDirectory) if err != nil { - logrus.Errorf("cannot tar container entries %v error: %v", entries, err) + logrus.Errorf("cannot find absolute path of %v: %v", options.ContextDirectory, err) return nil, err } - defer func() { - if err := tarfile.Close(); err != nil { - logrus.Errorf("%v\n", err) + + tarContent := []string{options.ContextDirectory} + newContainerFiles := []string{} + for _, c := range containerFiles { + containerfile, err := filepath.Abs(c) + if err != nil { + logrus.Errorf("cannot find absolute path of %v: %v", c, err) + return nil, err } - }() - containerFile, err := filepath.Abs(entries[0]) - if err != nil { - logrus.Errorf("cannot find absolute path of %v: %v", entries[0], err) - return nil, err + // Check if Containerfile is in the context directory, if so truncate the contextdirectory off path + // Do NOT add to tarfile + if strings.HasPrefix(containerfile, contextDir+string(filepath.Separator)) { + containerfile = strings.TrimPrefix(containerfile, contextDir+string(filepath.Separator)) + } else { + // If Containerfile does not exists assume it is in context directory, do Not add to tarfile + if _, err := os.Lstat(containerfile); err != nil { + if !os.IsNotExist(err) { + return nil, err + } + containerfile = c + } else { + // If Containerfile does exists but is not in context directory add it to the tarfile + tarContent = append(tarContent, containerfile) + } + } + newContainerFiles = append(newContainerFiles, containerfile) } - contextDir, err := filepath.Abs(entries[1]) - if err != nil { - logrus.Errorf("cannot find absolute path of %v: %v", entries[1], err) - return nil, err + if len(newContainerFiles) > 0 { + cFileJSON, err := json.Marshal(newContainerFiles) + if err != nil { + return nil, err + } + params.Set("dockerfile", string(cFileJSON)) } - if strings.HasPrefix(containerFile, contextDir+string(filepath.Separator)) { - containerFile = strings.TrimPrefix(containerFile, contextDir+string(filepath.Separator)) + tarfile, err := nTar(excludes, tarContent...) + if err != nil { + logrus.Errorf("cannot tar container entries %v error: %v", tarContent, err) + return nil, err } - - params.Set("dockerfile", containerFile) + defer func() { + if err := tarfile.Close(); err != nil { + logrus.Errorf("%v\n", err) + } + }() conn, err := bindings.GetClient(ctx) if err != nil { diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 0f3f3fa7fa..40622d6ccc 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -794,6 +794,32 @@ EOF run_podman rmi -f build_test } +@test "podman build -f test " { + tmpdir=$PODMAN_TMPDIR/build-test + subdir=$tmpdir/subdir + mkdir -p $subdir + + containerfile1=$tmpdir/Containerfile1 + cat >$containerfile1 <$containerfile2 < Date: Thu, 13 May 2021 14:39:06 +0200 Subject: [PATCH 06/21] Several shell completion fixes - fix network filters - add prune filters - pod create --share support comma separated namespaces [NO TESTS NEEDED] Signed-off-by: Paul Holzinger --- cmd/podman/common/completion.go | 51 +++++++++++++++++----- cmd/podman/containers/prune.go | 2 +- cmd/podman/images/prune.go | 4 +- cmd/podman/networks/prune.go | 3 +- cmd/podman/system/prune.go | 3 +- docs/source/markdown/podman-volume-ls.1.md | 9 +++- 6 files changed, 54 insertions(+), 18 deletions(-) diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 4aca797706..de5b2995a0 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -11,6 +11,7 @@ import ( "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/network" "github.com/containers/podman/v3/pkg/registries" "github.com/containers/podman/v3/pkg/rootless" systemdDefine "github.com/containers/podman/v3/pkg/systemd/define" @@ -243,7 +244,7 @@ func getRegistries() ([]string, cobra.ShellCompDirective) { return regs, cobra.ShellCompDirectiveNoFileComp } -func getNetworks(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) { +func getNetworks(cmd *cobra.Command, toComplete string, cType completeType) ([]string, cobra.ShellCompDirective) { suggestions := []string{} networkListOptions := entities.NetworkListOptions{} @@ -259,7 +260,15 @@ func getNetworks(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCo } for _, n := range networks { - if strings.HasPrefix(n.Name, toComplete) { + id := network.GetNetworkID(n.Name) + // include ids in suggestions if cType == completeIDs or + // more then 2 chars are typed and cType == completeDefault + if ((len(toComplete) > 1 && cType == completeDefault) || + cType == completeIDs) && strings.HasPrefix(id, toComplete) { + suggestions = append(suggestions, id[0:12]) + } + // include name in suggestions + if cType != completeIDs && strings.HasPrefix(n.Name, toComplete) { suggestions = append(suggestions, n.Name) } } @@ -502,7 +511,7 @@ func AutocompleteNetworks(cmd *cobra.Command, args []string, toComplete string) if !validCurrentCmdLine(cmd, args, toComplete) { return nil, cobra.ShellCompDirectiveNoFileComp } - return getNetworks(cmd, toComplete) + return getNetworks(cmd, toComplete, completeDefault) } // AutocompleteDefaultOneArg - Autocomplete path only for the first argument. @@ -588,7 +597,7 @@ func AutocompleteContainerOneArg(cmd *cobra.Command, args []string, toComplete s // AutocompleteNetworkConnectCmd - Autocomplete podman network connect/disconnect command args. func AutocompleteNetworkConnectCmd(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return getNetworks(cmd, toComplete) + return getNetworks(cmd, toComplete, completeDefault) } if len(args) == 1 { return getContainers(cmd, toComplete, completeDefault) @@ -624,7 +633,7 @@ func AutocompleteInspect(cmd *cobra.Command, args []string, toComplete string) ( containers, _ := getContainers(cmd, toComplete, completeDefault) images, _ := getImages(cmd, toComplete) pods, _ := getPods(cmd, toComplete, completeDefault) - networks, _ := getNetworks(cmd, toComplete) + networks, _ := getNetworks(cmd, toComplete, completeDefault) volumes, _ := getVolumes(cmd, toComplete) suggestions := append(containers, images...) suggestions = append(suggestions, pods...) @@ -885,7 +894,7 @@ func AutocompleteNetworkFlag(cmd *cobra.Command, args []string, toComplete strin }, } - networks, _ := getNetworks(cmd, toComplete) + networks, _ := getNetworks(cmd, toComplete, completeDefault) suggestions, dir := completeKeyValues(toComplete, kv) // add slirp4netns here it does not work correct if we add it to the kv map suggestions = append(suggestions, "slirp4netns") @@ -1039,7 +1048,10 @@ func AutocompleteNetworkDriver(cmd *cobra.Command, args []string, toComplete str // -> "ipc", "net", "pid", "user", "uts", "cgroup", "none" func AutocompletePodShareNamespace(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { namespaces := []string{"ipc", "net", "pid", "user", "uts", "cgroup", "none"} - return namespaces, cobra.ShellCompDirectiveNoFileComp + split := strings.Split(toComplete, ",") + split[len(split)-1] = "" + toComplete = strings.Join(split, ",") + return prefixSlice(toComplete, namespaces), cobra.ShellCompDirectiveNoFileComp } // AutocompletePodPsSort - Autocomplete images sort options. @@ -1115,7 +1127,7 @@ func AutocompletePsFilters(cmd *cobra.Command, args []string, toComplete string) return []string{define.HealthCheckHealthy, define.HealthCheckUnhealthy}, cobra.ShellCompDirectiveNoFileComp }, - "network=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s) }, + "network=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s, completeDefault) }, "label=": nil, "exited=": nil, "until=": nil, @@ -1138,7 +1150,7 @@ func AutocompletePodPsFilters(cmd *cobra.Command, args []string, toComplete stri "ctr-status=": func(_ string) ([]string, cobra.ShellCompDirective) { return containerStatuses, cobra.ShellCompDirectiveNoFileComp }, - "network=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s) }, + "network=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s, completeDefault) }, "label=": nil, } return completeKeyValues(toComplete, kv) @@ -1158,11 +1170,28 @@ func AutocompleteImageFilters(cmd *cobra.Command, args []string, toComplete stri return completeKeyValues(toComplete, kv) } +// AutocompletePruneFilters - Autocomplete container/image prune --filter options. +func AutocompletePruneFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + kv := keyValueCompletion{ + "until=": nil, + "label=": nil, + } + return completeKeyValues(toComplete, kv) +} + // AutocompleteNetworkFilters - Autocomplete network ls --filter options. func AutocompleteNetworkFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { kv := keyValueCompletion{ - "name=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s) }, - "plugin=": nil, + "name=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s, completeNames) }, + "id=": func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s, completeIDs) }, + "plugin=": func(_ string) ([]string, cobra.ShellCompDirective) { + return []string{"bridge", "portmap", + "firewall", "tuning", "dnsname", "macvlan"}, cobra.ShellCompDirectiveNoFileComp + }, + "label=": nil, + "driver=": func(_ string) ([]string, cobra.ShellCompDirective) { + return []string{"bridge"}, cobra.ShellCompDirectiveNoFileComp + }, } return completeKeyValues(toComplete, kv) } diff --git a/cmd/podman/containers/prune.go b/cmd/podman/containers/prune.go index 837d90f70d..94da029b9c 100644 --- a/cmd/podman/containers/prune.go +++ b/cmd/podman/containers/prune.go @@ -43,7 +43,7 @@ func init() { flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation. The default is false") filterFlagName := "filter" flags.StringArrayVar(&filter, filterFlagName, []string{}, "Provide filter values (e.g. 'label==')") - _ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone) + _ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePruneFilters) } func prune(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go index 6849d5971f..db645cc2eb 100644 --- a/cmd/podman/images/prune.go +++ b/cmd/podman/images/prune.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/utils" "github.com/containers/podman/v3/cmd/podman/validate" @@ -44,8 +45,7 @@ func init() { filterFlagName := "filter" flags.StringArrayVar(&filter, filterFlagName, []string{}, "Provide filter values (e.g. 'label==')") - //TODO: add completion for filters - _ = pruneCmd.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone) + _ = pruneCmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePruneFilters) } func prune(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/networks/prune.go b/cmd/podman/networks/prune.go index bcc55f0f4f..5f1cbda5f1 100644 --- a/cmd/podman/networks/prune.go +++ b/cmd/podman/networks/prune.go @@ -6,7 +6,6 @@ import ( "os" "strings" - "github.com/containers/common/pkg/completion" "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/utils" @@ -39,7 +38,7 @@ func networkPruneFlags(cmd *cobra.Command, flags *pflag.FlagSet) { flags.BoolVarP(&force, "force", "f", false, "do not prompt for confirmation") filterFlagName := "filter" flags.StringArrayVar(&filter, filterFlagName, []string{}, "Provide filter values (e.g. 'label==')") - _ = cmd.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone) + _ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePruneFilters) } func init() { diff --git a/cmd/podman/system/prune.go b/cmd/podman/system/prune.go index 3020a541be..0f12855645 100644 --- a/cmd/podman/system/prune.go +++ b/cmd/podman/system/prune.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/utils" @@ -50,7 +51,7 @@ func init() { flags.BoolVar(&pruneOptions.Volume, "volumes", false, "Prune volumes") filterFlagName := "filter" flags.StringArrayVar(&filters, filterFlagName, []string{}, "Provide filter values (e.g. 'label==')") - _ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone) + _ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePruneFilters) } func prune(cmd *cobra.Command, args []string) error { diff --git a/docs/source/markdown/podman-volume-ls.1.md b/docs/source/markdown/podman-volume-ls.1.md index ab3813cca1..489057446c 100644 --- a/docs/source/markdown/podman-volume-ls.1.md +++ b/docs/source/markdown/podman-volume-ls.1.md @@ -16,7 +16,14 @@ flag. Use the **--quiet** flag to print only the volume names. #### **--filter**=*filter*, **-f** -Filter volume output. +Volumes can be filtered by the following attributes: + +- dangling +- driver +- label +- name +- opt +- scope #### **--format**=*format* From f1e7a07473958a9ba0f06f7c2f88105200f7a146 Mon Sep 17 00:00:00 2001 From: Jakub Guzik Date: Thu, 3 Jun 2021 22:48:43 +0200 Subject: [PATCH 07/21] Fix image prune --filter cmd behavior Image prune --filter is fully implemented in the api, http api yet not connected with the cli execution. User trying to use filters does not see the effect. This commit adds glue code to enable possiblity of using --filter in prune in the cli execution. Signed-off-by: Jakub Guzik --- cmd/podman/images/prune.go | 10 +++++++++- test/e2e/common_test.go | 39 +++++++++++++++++++++++++------------- test/e2e/images_test.go | 21 ++++++++++++++++++++ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go index db645cc2eb..52217c0d61 100644 --- a/cmd/podman/images/prune.go +++ b/cmd/podman/images/prune.go @@ -60,7 +60,15 @@ func prune(cmd *cobra.Command, args []string) error { return nil } } - + filterMap, err := common.ParseFilters(filter) + if err != nil { + return err + } + for k, v := range filterMap { + for _, val := range v { + pruneOpts.Filter = append(pruneOpts.Filter, fmt.Sprintf("%s=%s", k, val)) + } + } results, err := registry.ImageEngine().Prune(registry.GetContext(), pruneOpts) if err != nil { return err diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 7ffee961ce..1aeeca4cb4 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -451,19 +451,13 @@ func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSe // BuildImage uses podman build and buildah to build an image // called imageName based on a string dockerfile func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) string { - dockerfilePath := filepath.Join(p.TempDir, "Dockerfile") - err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755) - Expect(err).To(BeNil()) - cmd := []string{"build", "--pull-never", "--layers=" + layers, "--file", dockerfilePath} - if len(imageName) > 0 { - cmd = append(cmd, []string{"-t", imageName}...) - } - cmd = append(cmd, p.TempDir) - session := p.Podman(cmd) - session.Wait(240) - Expect(session).Should(Exit(0), fmt.Sprintf("BuildImage session output: %q", session.OutputToString())) - output := session.OutputToStringArray() - return output[len(output)-1] + return p.buildImage(dockerfile, imageName, layers, "") +} + +// BuildImageWithLabel uses podman build and buildah to build an image +// called imageName based on a string dockerfile, adds desired label to paramset +func (p *PodmanTestIntegration) BuildImageWithLabel(dockerfile, imageName string, layers string, label string) string { + return p.buildImage(dockerfile, imageName, layers, label) } // PodmanPID execs podman and returns its PID @@ -828,3 +822,22 @@ func (p *PodmanSessionIntegration) jq(jqCommand string) (string, error) { err := cmd.Run() return strings.TrimRight(out.String(), "\n"), err } + +func (p *PodmanTestIntegration) buildImage(dockerfile, imageName string, layers string, label string) string { + dockerfilePath := filepath.Join(p.TempDir, "Dockerfile") + err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755) + Expect(err).To(BeNil()) + cmd := []string{"build", "--pull-never", "--layers=" + layers, "--file", dockerfilePath} + if label != "" { + cmd = append(cmd, "--label="+label) + } + if len(imageName) > 0 { + cmd = append(cmd, []string{"-t", imageName}...) + } + cmd = append(cmd, p.TempDir) + session := p.Podman(cmd) + session.Wait(240) + Expect(session).Should(Exit(0), fmt.Sprintf("BuildImage session output: %q", session.OutputToString())) + output := session.OutputToStringArray() + return output[len(output)-1] +} diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go index f6321ec1c4..b4ec7447e0 100644 --- a/test/e2e/images_test.go +++ b/test/e2e/images_test.go @@ -425,4 +425,25 @@ LABEL "com.example.vendor"="Example Vendor" Expect(result.OutputToStringArray()).To(Not(Equal(result1.OutputToStringArray()))) }) + It("podman image prune --filter", func() { + dockerfile := `FROM quay.io/libpod/alpine:latest +RUN > file +` + dockerfile2 := `FROM quay.io/libpod/alpine:latest +RUN > file2 +` + podmanTest.BuildImageWithLabel(dockerfile, "foobar.com/workdir:latest", "false", "abc") + podmanTest.BuildImageWithLabel(dockerfile2, "foobar.com/workdir:latest", "false", "xyz") + // --force used to to avoid y/n question + result := podmanTest.Podman([]string{"image", "prune", "--filter", "label=abc", "--force"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(len(result.OutputToStringArray())).To(Equal(1)) + + //check if really abc is removed + result = podmanTest.Podman([]string{"image", "list", "--filter", "label=abc"}) + Expect(len(result.OutputToStringArray())).To(Equal(0)) + + }) + }) From c3f6ef63a27ae23f79995c4019d552ed4dfdd406 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Tue, 8 Jun 2021 13:44:49 +0200 Subject: [PATCH 08/21] logs: k8s-file: fix race Fix a race in the k8s-file logs driver. When "following" the logs, Podman will print the container's logs until the end. Previously, Podman logged until the state transitioned into something non-running which opened up a race with the container still running, possibly in the "stopping" state. To fix the race, log until we've seen the wait event for the specific container. In that case, conmon will have finished writing all logs to the file, and Podman will read it until EOF. Further tweak the integration tests for testing `logs -f` on a running container. Previously, the test only checked for one of two lines stating that there was a race. Indeed the race was in using `run --rm` where a log file may be removed before we could fully read it. Fixes: #10596 Signed-off-by: Valentin Rothberg --- libpod/container_log.go | 54 +++++++++++++++++++++++++---------------- test/e2e/logs_test.go | 14 ++++++----- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/libpod/container_log.go b/libpod/container_log.go index c207df8199..a30e4f5cc0 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -4,11 +4,10 @@ import ( "context" "fmt" "os" - "time" "github.com/containers/podman/v3/libpod/define" + "github.com/containers/podman/v3/libpod/events" "github.com/containers/podman/v3/libpod/logs" - "github.com/hpcloud/tail/watch" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -94,27 +93,40 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption }() // Check if container is still running or paused if options.Follow { + state, err := c.State() + if err != nil || state != define.ContainerStateRunning { + // If the container isn't running or if we encountered + // an error getting its state, instruct the logger to + // read the file until EOF. + tailError := t.StopAtEOF() + if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { + logrus.Error(tailError) + } + if errors.Cause(err) != define.ErrNoSuchCtr { + logrus.Error(err) + } + return nil + } + + // The container is running, so we need to wait until the container exited go func() { - for { - state, err := c.State() - time.Sleep(watch.POLL_DURATION) - if err != nil { - tailError := t.StopAtEOF() - if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { - logrus.Error(tailError) - } - if errors.Cause(err) != define.ErrNoSuchCtr { - logrus.Error(err) - } - break - } - if state != define.ContainerStateRunning && state != define.ContainerStatePaused { - tailError := t.StopAtEOF() - if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { - logrus.Error(tailError) - } - break + eventChannel := make(chan *events.Event) + eventOptions := events.ReadOptions{ + EventChannel: eventChannel, + Filters: []string{"event=died", "container=" + c.ID()}, + Stream: true, + } + go func() { + if err := c.runtime.Events(ctx, eventOptions); err != nil { + logrus.Errorf("Error waiting for container to exit: %v", err) } + }() + // Now wait for the died event and signal to finish + // reading the log until EOF. + <-eventChannel + tailError := t.StopAtEOF() + if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { + logrus.Error(tailError) } }() } diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index 3051031a53..b7a5a6243c 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -173,9 +173,9 @@ var _ = Describe("Podman logs", func() { }) It("streaming output: "+log, func() { - containerName := "logs-f-rm" + containerName := "logs-f" - logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--rm", "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman; sleep 1; echo podman"}) + logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman-1; sleep 1; echo podman-2"}) logc.WaitWithDefaultTimeout() Expect(logc).To(Exit(0)) @@ -183,10 +183,8 @@ var _ = Describe("Podman logs", func() { results.WaitWithDefaultTimeout() Expect(results).To(Exit(0)) - // TODO: we should actually check for two podman lines, - // but as of 2020-06-17 there's a race condition in which - // 'logs -f' may not catch all output from a container - Expect(results.OutputToString()).To(ContainSubstring("podman")) + Expect(results.OutputToString()).To(ContainSubstring("podman-1")) + Expect(results.OutputToString()).To(ContainSubstring("podman-2")) // Container should now be terminatING or terminatED, but we // have no guarantee of which: 'logs -f' does not necessarily @@ -199,6 +197,10 @@ var _ = Describe("Podman logs", func() { } else { Expect(inspect.ErrorToString()).To(ContainSubstring("no such container")) } + + results = podmanTest.Podman([]string{"rm", "-f", containerName}) + results.WaitWithDefaultTimeout() + Expect(results).To(Exit(0)) }) It("follow output stopped container: "+log, func() { From 8ba0c92e6a8da59417d7e96a6f2002bfe1a74f1f Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 8 Jun 2021 11:28:46 +0200 Subject: [PATCH 09/21] Improve systemd-resolved detection When 127.0.0.53 is the only nameserver in /etc/resolv.conf assume systemd-resolved is used. This is better because /etc/resolv.conf does not have to be symlinked to /run/systemd/resolve/stub-resolv.conf in order to use systemd-resolved. [NO TESTS NEEDED] Fixes: #10570 Signed-off-by: Paul Holzinger --- libpod/container_internal_linux.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index bf235e42c8..be59e3b54f 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1649,22 +1649,20 @@ func (c *Container) generateResolvConf() (string, error) { } } - // Determine the endpoint for resolv.conf in case it is a symlink - resolvPath, err := filepath.EvalSymlinks(resolvConf) + contents, err := ioutil.ReadFile(resolvConf) // resolv.conf doesn't have to exists if err != nil && !os.IsNotExist(err) { return "", err } - // Determine if symlink points to any of the systemd-resolved files - if strings.HasPrefix(resolvPath, "/run/systemd/resolve/") { - resolvPath = "/run/systemd/resolve/resolv.conf" - } - - contents, err := ioutil.ReadFile(resolvPath) - // resolv.conf doesn't have to exists - if err != nil && !os.IsNotExist(err) { - return "", err + ns := resolvconf.GetNameservers(contents) + // check if systemd-resolved is used, assume it is used when 127.0.0.53 is the only nameserver + if len(ns) == 1 && ns[0] == "127.0.0.53" { + // read the actual resolv.conf file for systemd-resolved + contents, err = ioutil.ReadFile("/run/systemd/resolve/resolv.conf") + if err != nil { + return "", errors.Wrapf(err, "detected that systemd-resolved is in use, but could not locate real resolv.conf") + } } ipv6 := false From 2993bdf1efe11823e6448993dad4deb3d9f27c2d Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 8 Jun 2021 10:55:02 +0200 Subject: [PATCH 10/21] Fix network prune api docs The api doc used wrong response examples for both the compat and libpod network prune endpoints. Change the doc so that it matches the actual return values. Also fix the endpoints to return an empty array instead of null when no networks are removed. [NO TESTS NEEDED] Fixes: #10564 Signed-off-by: Paul Holzinger --- pkg/api/handlers/compat/networks.go | 2 +- pkg/api/handlers/compat/swagger.go | 7 ------- pkg/api/handlers/libpod/networks.go | 3 +++ pkg/api/handlers/libpod/swagger.go | 7 +++++++ pkg/api/server/register_networks.go | 9 ++++++--- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go index 77ed548d83..04f8570ff8 100644 --- a/pkg/api/handlers/compat/networks.go +++ b/pkg/api/handlers/compat/networks.go @@ -414,7 +414,7 @@ func Prune(w http.ResponseWriter, r *http.Request) { type response struct { NetworksDeleted []string } - var prunedNetworks []string //nolint + prunedNetworks := []string{} for _, pr := range pruneReports { if pr.Error != nil { logrus.Error(pr.Error) diff --git a/pkg/api/handlers/compat/swagger.go b/pkg/api/handlers/compat/swagger.go index a0783e723e..b773799eff 100644 --- a/pkg/api/handlers/compat/swagger.go +++ b/pkg/api/handlers/compat/swagger.go @@ -77,10 +77,3 @@ type swagCompatNetworkDisconnectRequest struct { // in:body Body struct{ types.NetworkDisconnect } } - -// Network prune -// swagger:response NetworkPruneResponse -type swagCompatNetworkPruneResponse struct { - // in:body - Body []string -} diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go index 5417f778e6..e4f450e12e 100644 --- a/pkg/api/handlers/libpod/networks.go +++ b/pkg/api/handlers/libpod/networks.go @@ -190,5 +190,8 @@ func Prune(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) return } + if pruneReports == nil { + pruneReports = []*entities.NetworkPruneReport{} + } utils.WriteResponse(w, http.StatusOK, pruneReports) } diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go index 9450a70d93..f805954295 100644 --- a/pkg/api/handlers/libpod/swagger.go +++ b/pkg/api/handlers/libpod/swagger.go @@ -119,6 +119,13 @@ type swagNetworkCreateReport struct { Body entities.NetworkCreateReport } +// Network prune +// swagger:response NetworkPruneResponse +type swagNetworkPruneResponse struct { + // in:body + Body []entities.NetworkPruneReport +} + func ServeSwagger(w http.ResponseWriter, r *http.Request) { path := DefaultPodmanSwaggerSpec if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found { diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go index dcec61befc..85d008e76c 100644 --- a/pkg/api/server/register_networks.go +++ b/pkg/api/server/register_networks.go @@ -180,9 +180,12 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error { // 200: // description: OK // schema: - // type: array - // items: - // type: string + // type: object + // properties: + // NetworksDeleted: + // type: array + // items: + // type: string // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/networks/prune"), s.APIHandler(compat.Prune)).Methods(http.MethodPost) From c28f442b28cf858feb0e7d9d6ee77df708030cd5 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 8 Jun 2021 13:29:23 +0200 Subject: [PATCH 11/21] remote pull: cancel pull when connection is closed If a client closes the http connection during image pull, the service should cancel the pull operation. [NO TESTS NEEDED] I have no idea how we could test this reliable. Fixes: #7558 Signed-off-by: Paul Holzinger --- pkg/api/handlers/libpod/images_pull.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go index 7545ba2350..73d08a26e1 100644 --- a/pkg/api/handlers/libpod/images_pull.go +++ b/pkg/api/handlers/libpod/images_pull.go @@ -85,7 +85,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { var pulledImages []*libimage.Image var pullError error - runCtx, cancel := context.WithCancel(context.Background()) + runCtx, cancel := context.WithCancel(r.Context()) go func() { defer cancel() pulledImages, pullError = runtime.LibimageRuntime().Pull(runCtx, query.Reference, config.PullPolicyAlways, pullOptions) From c751544facb3fb891f40d4d125940a51c0477494 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Fri, 4 Jun 2021 13:15:33 +0200 Subject: [PATCH 12/21] remote events: support labels Certain event meta data was lost when converting the remote events to libpod events and vice versa. Enable the skipped system tests for remote. Signed-off-by: Valentin Rothberg --- pkg/domain/entities/events.go | 28 ++++++++++++++++++++-------- test/e2e/events_test.go | 13 +++++-------- test/system/090-events.bats | 1 - 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/pkg/domain/entities/events.go b/pkg/domain/entities/events.go index 930ca53aeb..5e7cc9ad1e 100644 --- a/pkg/domain/entities/events.go +++ b/pkg/domain/entities/events.go @@ -30,29 +30,41 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event { if err != nil { return nil } + image := e.Actor.Attributes["image"] + name := e.Actor.Attributes["name"] + details := e.Actor.Attributes + delete(details, "image") + delete(details, "name") + delete(details, "containerExitCode") return &libpodEvents.Event{ ContainerExitCode: exitCode, ID: e.Actor.ID, - Image: e.Actor.Attributes["image"], - Name: e.Actor.Attributes["name"], + Image: image, + Name: name, Status: status, Time: time.Unix(e.Time, e.TimeNano), Type: t, + Details: libpodEvents.Details{ + Attributes: details, + }, } } // ConvertToEntitiesEvent converts a libpod event to an entities one. func ConvertToEntitiesEvent(e libpodEvents.Event) *Event { + attributes := e.Details.Attributes + if attributes == nil { + attributes = make(map[string]string) + } + attributes["image"] = e.Image + attributes["name"] = e.Name + attributes["containerExitCode"] = strconv.Itoa(e.ContainerExitCode) return &Event{dockerEvents.Message{ Type: e.Type.String(), Action: e.Status.String(), Actor: dockerEvents.Actor{ - ID: e.ID, - Attributes: map[string]string{ - "image": e.Image, - "name": e.Name, - "containerExitCode": strconv.Itoa(e.ContainerExitCode), - }, + ID: e.ID, + Attributes: attributes, }, Scope: "local", Time: e.Time.Unix(), diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go index 4dbbe9dd82..cc7c4d9961 100644 --- a/test/e2e/events_test.go +++ b/test/e2e/events_test.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "github.com/containers/podman/v3/libpod/events" . "github.com/containers/podman/v3/test/utils" "github.com/containers/storage/pkg/stringid" . "github.com/onsi/ginkgo" @@ -134,12 +135,10 @@ var _ = Describe("Podman events", func() { jsonArr := test.OutputToStringArray() Expect(test.OutputToStringArray()).ShouldNot(BeEmpty()) - eventsMap := make(map[string]string) - err := json.Unmarshal([]byte(jsonArr[0]), &eventsMap) + event := events.Event{} + err := json.Unmarshal([]byte(jsonArr[0]), &event) Expect(err).ToNot(HaveOccurred()) - Expect(eventsMap).To(HaveKey("Status")) - test = podmanTest.Podman([]string{"events", "--stream=false", "--format", "{{json.}}"}) test.WaitWithDefaultTimeout() Expect(test).To(Exit(0)) @@ -147,11 +146,9 @@ var _ = Describe("Podman events", func() { jsonArr = test.OutputToStringArray() Expect(test.OutputToStringArray()).ShouldNot(BeEmpty()) - eventsMap = make(map[string]string) - err = json.Unmarshal([]byte(jsonArr[0]), &eventsMap) + event = events.Event{} + err = json.Unmarshal([]byte(jsonArr[0]), &event) Expect(err).ToNot(HaveOccurred()) - - Expect(eventsMap).To(HaveKey("Status")) }) It("podman events --until future", func() { diff --git a/test/system/090-events.bats b/test/system/090-events.bats index 09c2d0c10c..7948cd1e61 100644 --- a/test/system/090-events.bats +++ b/test/system/090-events.bats @@ -6,7 +6,6 @@ load helpers @test "events with a filter by label" { - skip_if_remote "FIXME: -remote does not include labels in event output" cname=test-$(random_string 30 | tr A-Z a-z) labelname=$(random_string 10) labelvalue=$(random_string 15) From 26eae3bf89bcaf486ee297088102161d9c02311a Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 3 Jun 2021 16:07:43 +0200 Subject: [PATCH 13/21] remote: always send resize before the container starts There is race condition in the remote client attach logic. Because the resize api call was handled in an extra goroutine the container was started before the resize call happend. To fix this we have to call resize in the same goroutine as attach. When the first resize is done start a goroutine to listen on SIGWINCH in the background and resize again if the signal is received. Fixes #9859 Signed-off-by: Paul Holzinger Signed-off-by: Matthew Heon --- pkg/api/handlers/compat/resize.go | 15 ++------ pkg/api/server/register_containers.go | 2 + pkg/bindings/containers/attach.go | 54 +++++++++++++++------------ test/system/450-interactive.bats | 3 +- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go index 23ed33a22c..f65e313fc7 100644 --- a/pkg/api/handlers/compat/resize.go +++ b/pkg/api/handlers/compat/resize.go @@ -46,20 +46,13 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { utils.ContainerNotFound(w, name, err) return } - if state, err := ctnr.State(); err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "cannot obtain container state")) - return - } else if state != define.ContainerStateRunning && !query.IgnoreNotRunning { - utils.Error(w, "Container not running", http.StatusConflict, - fmt.Errorf("container %q in wrong state %q", name, state.String())) - return - } - // If container is not running, ignore since this can be a race condition, and is expected if err := ctnr.AttachResize(sz); err != nil { - if errors.Cause(err) != define.ErrCtrStateInvalid || !query.IgnoreNotRunning { + if errors.Cause(err) != define.ErrCtrStateInvalid { utils.InternalServerError(w, errors.Wrapf(err, "cannot resize container")) - return + } else { + utils.Error(w, "Container not running", http.StatusConflict, err) } + return } // This is not a 204, even though we write nothing, for compatibility // reasons. diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 536c4707a9..2a6e8e2865 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -1359,6 +1359,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // $ref: "#/responses/ok" // 404: // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/resize"), s.APIHandler(compat.ResizeTTY)).Methods(http.MethodPost) diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index fd8a7011dc..adef1e7c84 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -138,7 +138,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri winCtx, winCancel := context.WithCancel(ctx) defer winCancel() - go attachHandleResize(ctx, winCtx, winChange, false, nameOrID, file) + attachHandleResize(ctx, winCtx, winChange, false, nameOrID, file) } // If we are attaching around a start, we need to "signal" @@ -327,32 +327,38 @@ func (f *rawFormatter) Format(entry *logrus.Entry) ([]byte, error) { return append(buffer, '\r'), nil } -// This is intended to be run as a goroutine, handling resizing for a container -// or exec session. +// This is intended to not be run as a goroutine, handling resizing for a container +// or exec session. It will call resize once and then starts a goroutine which calls resize on winChange func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, isExec bool, id string, file *os.File) { - // Prime the pump, we need one reset to ensure everything is ready - winChange <- sig.SIGWINCH - for { - select { - case <-winCtx.Done(): - return - case <-winChange: - w, h, err := terminal.GetSize(int(file.Fd())) - if err != nil { - logrus.Warnf("failed to obtain TTY size: %v", err) - } + resize := func() { + w, h, err := terminal.GetSize(int(file.Fd())) + if err != nil { + logrus.Warnf("failed to obtain TTY size: %v", err) + } - var resizeErr error - if isExec { - resizeErr = ResizeExecTTY(ctx, id, new(ResizeExecTTYOptions).WithHeight(h).WithWidth(w)) - } else { - resizeErr = ResizeContainerTTY(ctx, id, new(ResizeTTYOptions).WithHeight(h).WithWidth(w)) - } - if resizeErr != nil { - logrus.Warnf("failed to resize TTY: %v", resizeErr) - } + var resizeErr error + if isExec { + resizeErr = ResizeExecTTY(ctx, id, new(ResizeExecTTYOptions).WithHeight(h).WithWidth(w)) + } else { + resizeErr = ResizeContainerTTY(ctx, id, new(ResizeTTYOptions).WithHeight(h).WithWidth(w)) + } + if resizeErr != nil { + logrus.Warnf("failed to resize TTY: %v", resizeErr) } } + + resize() + + go func() { + for { + select { + case <-winCtx.Done(): + return + case <-winChange: + resize() + } + } + }() } // Configure the given terminal for raw mode @@ -457,7 +463,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar winCtx, winCancel := context.WithCancel(ctx) defer winCancel() - go attachHandleResize(ctx, winCtx, winChange, true, sessionID, terminalFile) + attachHandleResize(ctx, winCtx, winChange, true, sessionID, terminalFile) } if options.GetAttachInput() { diff --git a/test/system/450-interactive.bats b/test/system/450-interactive.bats index a9bf52ee8c..a2db39492c 100644 --- a/test/system/450-interactive.bats +++ b/test/system/450-interactive.bats @@ -56,8 +56,7 @@ function teardown() { stty rows $rows cols $cols <$PODMAN_TEST_PTY # ...and make sure stty under podman reads that. - # FIXME: 'sleep 1' is needed for podman-remote; without it, there's - run_podman run -it --name mystty $IMAGE sh -c 'sleep 1;stty size' <$PODMAN_TEST_PTY + run_podman run -it --name mystty $IMAGE stty size <$PODMAN_TEST_PTY is "$output" "$rows $cols" "stty under podman reads the correct dimensions" } From 38fbd2cb9edbe232d6ec7c8b107c50bab34da8e5 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Fri, 4 Jun 2021 14:22:52 +0200 Subject: [PATCH 14/21] [CI:DOCS] fix incorrect network remove api doc The endpoint returns an array and not a single entry. Fixes #10494 Signed-off-by: Paul Holzinger --- pkg/api/handlers/libpod/swagger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go index f805954295..2ac5009fc2 100644 --- a/pkg/api/handlers/libpod/swagger.go +++ b/pkg/api/handlers/libpod/swagger.go @@ -95,7 +95,7 @@ type swagInfoResponse struct { // swagger:response NetworkRmReport type swagNetworkRmReport struct { // in:body - Body entities.NetworkRmReport + Body []entities.NetworkRmReport } // Network inspect From 5a158563c05ea533d95b73793462941bbea01281 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Fri, 4 Jun 2021 11:28:00 +0200 Subject: [PATCH 15/21] remote events: fix --stream=false Fix a bug in remote events where only one event would be sent if when streaming is turned off. The source of the bug was that the handler attempted to implement the streaming logic and did it wrong. The fix is rather simple by removing this logic from the handler and let the events backend handle streaming. Fixes: #10529 Signed-off-by: Valentin Rothberg --- pkg/api/handlers/compat/events.go | 2 +- test/system/090-events.bats | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go index 405e616c58..9fbac91e0b 100644 --- a/pkg/api/handlers/compat/events.go +++ b/pkg/api/handlers/compat/events.go @@ -75,7 +75,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) { coder := json.NewEncoder(w) coder.SetEscapeHTML(true) - for stream := true; stream; stream = query.Stream { + for { select { case err := <-errorChannel: if err != nil { diff --git a/test/system/090-events.bats b/test/system/090-events.bats index 7948cd1e61..d889bd7f97 100644 --- a/test/system/090-events.bats +++ b/test/system/090-events.bats @@ -26,7 +26,7 @@ load helpers } @test "image events" { - skip_if_remote "FIXME: remove events on podman-remote seem to be broken" + skip_if_remote "remote does not support --events-backend" pushedDir=$PODMAN_TMPDIR/dir mkdir -p $pushedDir @@ -85,7 +85,5 @@ function _events_disjunctive_filters() { } @test "events with disjunctive filters - default" { - # NOTE: the last event for bar doesn't show up reliably. - skip_if_remote "FIXME #10529: remote events lose data" _events_disjunctive_filters "" } From f69789155aea0e41ab78c36d1ace9f7e57d44a68 Mon Sep 17 00:00:00 2001 From: Alex Schultz Date: Fri, 11 Jun 2021 11:13:19 -0600 Subject: [PATCH 16/21] Fall back to string for dockerfile parameter a9cb824981db3fee6b8445b29e513c89e9b9b00b changed the expectations of the dockerfile parameter to be json data however it's a string. In order to support both, let's attempt json and fall back to a string if the json parsing fails. Closes #10660 Signed-off-by: Alex Schultz --- pkg/api/handlers/compat/images_build.go | 4 +-- test/apiv2/10-images.at | 35 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 50423fb96a..9c4dd8638a 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -144,8 +144,8 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { if _, found := r.URL.Query()["dockerfile"]; found { var m = []string{} if err := json.Unmarshal([]byte(query.Dockerfile), &m); err != nil { - utils.BadRequest(w, "dockerfile", query.Dockerfile, err) - return + // it's not json, assume just a string + m = append(m, query.Dockerfile) } containerFiles = m } else { diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index 037a4c01f6..9e464dbc7e 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -147,4 +147,39 @@ t GET "images/get?names=alpine&names=busybox" 200 '[POSIX tar archive]' img_cnt=$(tar xf "$WORKDIR/curl.result.out" manifest.json -O | jq "length") is "$img_cnt" 2 "number of images in tar archive" +# check build works when uploading container file as a tar, see issue #10660 +TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX) +function cleanBuildTest() { + podman rmi -a -f + rm -rf "${TMPD}" &> /dev/null +} +CONTAINERFILE_TAR="${TMPD}/containerfile.tar" +cat > $TMPD/containerfile << EOF +FROM quay.io/libpod/alpine_labels:latest +EOF +tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_TAR} containerfile &> /dev/null + +curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ + -H "content-type: application/x-tar" \ + --dump-header "${TMPD}/headers.txt" \ + -o "${TMPD}/response.txt" \ + "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null + +BUILD_TEST_ERROR="" + +if ! grep -q '200 OK' "${TMPD}/headers.txt"; then + echo -e "${red}NOK: Image build from tar failed response was not 200 OK" + BUILD_TEST_ERROR="1" +fi + +if ! grep -q 'quay.io/libpod/alpine_labels' "${TMPD}/response.txt"; then + echo -e "${red}NOK: Image build from tar failed image name not in response" + BUILD_TEST_ERROR="1" +fi + +cleanBuildTest +if [[ "${BUILD_TEST_ERROR}" ]]; then + exit 1 +fi + # vim: filetype=sh From e42d727a97e4a5486d8a972a0e526e2e6afc83a9 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 11 Jun 2021 14:16:47 -0400 Subject: [PATCH 17/21] Revert "Ensure minimum API version is set correctly in tests" This reverts commit 9647d88449f44028c9b870af74e5e44cb819ff9d. We reverted the API bump (was a mistake, should have been left at 3.1.0) and now we need to revert the test changes. Signed-off-by: Matthew Heon --- test/apiv2/01-basic.at | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at index ae078b9008..64aafa0137 100644 --- a/test/apiv2/01-basic.at +++ b/test/apiv2/01-basic.at @@ -19,7 +19,7 @@ for i in /version version; do t GET $i 200 \ .Components[0].Name="Podman Engine" \ .Components[0].Details.APIVersion~3[0-9.-]\\+ \ - .Components[0].Details.MinAPIVersion=3.2.0 \ + .Components[0].Details.MinAPIVersion=3.1.0 \ .Components[0].Details.Os=linux \ .ApiVersion=1.40 \ .MinAPIVersion=1.24 \ From 4f56f7f13335bfe3795526d7ba00e70dbdbdf380 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Fri, 11 Jun 2021 15:05:52 +0200 Subject: [PATCH 18/21] Fix network connect race with docker-compose Network connect/disconnect has to call the cni plugins when the network namespace is already configured. This is the case for `ContainerStateRunning` and `ContainerStateCreated`. This is important otherwise the network is not attached to this network namespace and libpod will throw errors like `network inspection mismatch...` This problem happened when using `docker-compose up` in attached mode. Signed-off-by: Paul Holzinger --- libpod/networking_linux.go | 4 ++-- test/compose/test-compose | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 0e8a4f7683..eb515c000b 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -1068,7 +1068,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro } c.newNetworkEvent(events.NetworkDisconnect, netName) - if c.state.State != define.ContainerStateRunning { + if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) { return nil } @@ -1123,7 +1123,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e return err } c.newNetworkEvent(events.NetworkConnect, netName) - if c.state.State != define.ContainerStateRunning { + if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) { return nil } if c.state.NetNS == nil { diff --git a/test/compose/test-compose b/test/compose/test-compose index 46ca80321b..a36eae942c 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -183,6 +183,8 @@ function test_port() { fi echo "# cat $WORKDIR/server.log:" cat $WORKDIR/server.log + echo "# cat $logfile:" + cat $logfile return fi From c5d9c0a6fafed649b9c7eb745abe028e7a0fbe50 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 11 Jun 2021 11:50:02 -0400 Subject: [PATCH 19/21] Updated release notes for v3.2.1 Signed-off-by: Matthew Heon --- RELEASE_NOTES.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c6efff5ddd..69c12221cd 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,31 @@ # Release Notes +## 3.2.1 +### Changes +- Podman now allows corrupt images (e.g. from restarting the system during an image pull) to be replaced by a `podman pull` of the same image (instead of requiring they be removed first, then re-pulled). + +### Bugfixes +- Fixed a bug where Podman would fail to start containers if a Seccomp profile was not available at `/usr/share/containers/seccomp.json` ([#10556](https://github.com/containers/podman/issues/10556)). +- Fixed a bug where the `podman machine start` command failed on OS X machines with the AMD64 architecture and certain QEMU versions ([#10555](https://github.com/containers/podman/issues/10555)). +- Fixed a bug where Podman would always use the slow path for joining the rootless user namespace. +- Fixed a bug where the `podman stats` command would fail on Cgroups v1 systems when run on a container running systemd ([#10602](https://github.com/containers/podman/issues/10602)). +- Fixed a bug where pre-checkpoint support for `podman container checkpoint` did not function correctly. +- Fixed a bug where the remote Podman client's `podman build` command did not properly handle the `-f` option ([#9871](https://github.com/containers/podman/issues/9871)). +- Fixed a bug where the remote Podman client's `podman run` command would sometimes not resize the container's terminal before execution began ([#9859](https://github.com/containers/podman/issues/9859)). +- Fixed a bug where the `--filter` option to the `podman image prune` command was nonfunctional. +- Fixed a bug where the `podman logs -f` command would exit before all output for a container was printed when the `k8s-file` log driver was in use ([#10596](https://github.com/containers/podman/issues/10596)). +- Fixed a bug where Podman would not correctly detect that systemd-resolved was in use on the host and adjust DNS servers in the container appropriately under some circumstances ([#10570](https://github.com/containers/podman/issues/10570)). +- Fixed a bug where the `podman network connect` and `podman network disconnect` commands acted improperly when containers were in the Created state, marking the changes as done but not actually performing them. + +### API +- Fixed a bug where the Compat and Libpod Prune endpoints for Networks returned null, instead of an empty array, when nothing was pruned. +- Fixed a bug where the Create API for Images would continue to pull images even if a client closed the connection mid-pull ([#7558](https://github.com/containers/podman/issues/7558)). +- Fixed a bug where the Events API did not include some information (including labels) when sending events. +- Fixed a bug where the Events API would, when streaming was not requested, send at most one event ([#10529](https://github.com/containers/podman/issues/10529)). + +### Misc +- Updated the containers/common library to v0.38.9 + ## 3.2.0 ### Features - Docker Compose is now supported with rootless Podman ([#9169](https://github.com/containers/podman/issues/9169)). From 152952fe6b18581615c3efd1fafef2d8142738e8 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 11 Jun 2021 11:51:55 -0400 Subject: [PATCH 20/21] Bump to v3.2.1 Also, revert minimum API version for the Libpod remote API to v3.1.0. Signed-off-by: Matthew Heon --- changelog.txt | 22 ++++++++++++++++++++++ version/version.go | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0441908e62..2686b5086a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,25 @@ +- Changelog for v3.2.1 (2021-06-11): + * Updated release notes for v3.2.1 + * remote events: fix --stream=false + * [CI:DOCS] fix incorrect network remove api doc + * remote: always send resize before the container starts + * remote events: support labels + * remote pull: cancel pull when connection is closed + * Fix network prune api docs + * Improve systemd-resolved detection + * logs: k8s-file: fix race + * Fix image prune --filter cmd behavior + * podman-remote build should handle -f option properly + * System tests: deal with crun 0.20.1 + * Fix build tags for pkg/machine... + * Fix pre-checkpointing + * container: ignore named hierarchies + * [v3.2] vendor containers/common@v0.38.9 + * rootless: fix fast join userns path + * [v3.2] vendor containers/common@v0.38.7 + * [v3.2] vendor containers/common@v0.38.6 + * Correct qemu options for Intel macs + - Changelog for v3.2.0 (2021-06-03): * Final release notes updates for v3.2.0 * add ipv6 nameservers only when the container has ipv6 enabled diff --git a/version/version.go b/version/version.go index 606eed5af4..00de7ac638 100644 --- a/version/version.go +++ b/version/version.go @@ -27,7 +27,7 @@ const ( // NOTE: remember to bump the version at the top // of the top-level README.md file when this is // bumped. -var Version = semver.MustParse("3.2.1-dev") +var Version = semver.MustParse("3.2.1") // See https://docs.docker.com/engine/api/v1.40/ // libpod compat handlers are expected to honor docker API versions @@ -38,7 +38,7 @@ var Version = semver.MustParse("3.2.1-dev") var APIVersion = map[Tree]map[Level]semver.Version{ Libpod: { CurrentAPI: Version, - MinimalAPI: semver.MustParse("3.2.0"), + MinimalAPI: semver.MustParse("3.1.0"), }, Compat: { CurrentAPI: semver.MustParse("1.40.0"), From 60752b3206c8e950c9ba496917ed39f3cab548d6 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 11 Jun 2021 11:52:59 -0400 Subject: [PATCH 21/21] Bump to v3.2.2-dev Signed-off-by: Matthew Heon --- contrib/spec/podman.spec.in | 2 +- version/version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 798dfb3d9f..b4a4e3c48c 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -36,7 +36,7 @@ Epoch: 99 %else Epoch: 0 %endif -Version: 3.2.1 +Version: 3.2.2 Release: #COMMITDATE#.git%{shortcommit0}%{?dist} Summary: Manage Pods, Containers and Container Images License: ASL 2.0 diff --git a/version/version.go b/version/version.go index 00de7ac638..2bb13bf805 100644 --- a/version/version.go +++ b/version/version.go @@ -27,7 +27,7 @@ const ( // NOTE: remember to bump the version at the top // of the top-level README.md file when this is // bumped. -var Version = semver.MustParse("3.2.1") +var Version = semver.MustParse("3.2.2-dev") // See https://docs.docker.com/engine/api/v1.40/ // libpod compat handlers are expected to honor docker API versions