Repository: containers/podman
Pull request #11361 (2021-08-30 17:45:47)

Bump to v3.3.1
Final backports, release notes, and release bump


Patch:
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 9649e7abb7..b9b94dbb31 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,17 @@
 # Release Notes
 
+## 3.3.1
+### Bugfixes
+- Fixed a bug where unit files created by `podman generate systemd` could not cleanup shut down containers when stopped by `systemctl stop` ([#11304](https://github.com/containers/podman/issues/11304)).
+- Fixed a bug where `podman machine` commands would not properly locate the `gvproxy` binary in some circumstances.
+- Fixed a bug where containers created as part of a pod using the `--pod-id-file` option would not join the pod's network namespace ([#11303](https://github.com/containers/podman/issues/11303)).
+- Fixed a bug where Podman, when using the systemd cgroups driver, could sometimes leak dbus sessions.
+- Fixed a bug where the `until` filter to `podman logs` and `podman events` was improperly handled, requiring input to be negated ([#11158](https://github.com/containers/podman/issues/11158)).
+- Fixed a bug where rootless containers using CNI networking run on systems using `systemd-resolved` for DNS would fail to start if resolved symlinked `/etc/resolv.conf` to an absolute path ([#11358](https://github.com/containers/podman/issues/11358)).
+
+### API
+- A large number of potential file descriptor leaks from improperly closing client connections have been fixed.
+
 ## 3.3.0
 ### Features
 - Containers inside VMs created by `podman machine` will now automatically handle port forwarding - containers in `podman machine` VMs that publish ports via `--publish` or `--publish-all` will have these ports not just forwarded on the VM, but also on the host system.
diff --git a/changelog.txt b/changelog.txt
index 6d8deaa40f..0f6271f5e4 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,4 +1,16 @@
-- Changelog for HEAD (2021-08-20):
+- Changelog for v3.3.1 (2021-08-30):
+  * Update release notes for v3.3.1
+  * rootless cni: resolve absolute symlinks correctly
+  * Add filter params description to volume list/prune docs
+  * logFile until flag issue
+  * Fix file descriptor leaks and add test
+  * utils.RunUnderSystemdScope(): always close Conn
+  * Use pod netns with --pod-id-file
+  * e2e tests: fix overlay: Unknown option vfs.imagestore
+  * change error comparison for exec.ErrNotFound
+  * generate systemd: use --cidfile again
+
+- Changelog for v3.3.0 (2021-08-20):
   * Final release notes for v3.3.0
   * Fix network aliases with network id
   * machine: compute sha256 as we read the image file
@@ -20,7 +32,7 @@
   * Skip cgroup-parent test due to frequent flakes
   * Cirrus: Fix not uploading logformatter html
 
-- Changelog for HEAD (2021-08-17):
+- Changelog for v3.3.0-rc3 (2021-08-17):
   * Release notes for v3.3.0-RC3
   * [v3.3] Bump c/storage to v1.34.1 and c/image to v5.15.1
   * fix gvproxy path search for macos
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index c88cf050e5..ba762ecbb5 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -84,7 +84,7 @@ func create(cmd *cobra.Command, args []string) error {
 	var (
 		err error
 	)
-	cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "")
+	cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "" && cliVals.PodIDFile == "")
 	if err != nil {
 		return err
 	}
diff --git a/cmd/podman/containers/logs.go b/cmd/podman/containers/logs.go
index 00a8d4b52f..1548c6c243 100644
--- a/cmd/podman/containers/logs.go
+++ b/cmd/podman/containers/logs.go
@@ -120,7 +120,7 @@ func logsFlags(cmd *cobra.Command) {
 func logs(_ *cobra.Command, args []string) error {
 	if logsOptions.SinceRaw != "" {
 		// parse time, error out if something is wrong
-		since, err := util.ParseInputTime(logsOptions.SinceRaw)
+		since, err := util.ParseInputTime(logsOptions.SinceRaw, true)
 		if err != nil {
 			return errors.Wrapf(err, "error parsing --since %q", logsOptions.SinceRaw)
 		}
@@ -128,7 +128,7 @@ func logs(_ *cobra.Command, args []string) error {
 	}
 	if logsOptions.UntilRaw != "" {
 		// parse time, error out if something is wrong
-		until, err := util.ParseInputTime(logsOptions.UntilRaw)
+		until, err := util.ParseInputTime(logsOptions.UntilRaw, false)
 		if err != nil {
 			return errors.Wrapf(err, "error parsing --until %q", logsOptions.UntilRaw)
 		}
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index 579af4eb10..830d1de7f2 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -106,7 +106,7 @@ func init() {
 
 func run(cmd *cobra.Command, args []string) error {
 	var err error
-	cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "")
+	cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "" && cliVals.PodIDFile == "")
 	if err != nil {
 		return err
 	}
diff --git a/cmd/podman/generate/kube.go b/cmd/podman/generate/kube.go
index b4c9f91461..60b8f0af02 100644
--- a/cmd/podman/generate/kube.go
+++ b/cmd/podman/generate/kube.go
@@ -2,6 +2,7 @@ package pods
 
 import (
 	"fmt"
+	"io"
 	"io/ioutil"
 	"os"
 
@@ -61,6 +62,10 @@ func kube(cmd *cobra.Command, args []string) error {
 	if err != nil {
 		return err
 	}
+	if r, ok := report.Reader.(io.ReadCloser); ok {
+		defer r.Close()
+	}
+
 	if cmd.Flags().Changed("filename") {
 		if _, err := os.Stat(kubeFile); err == nil {
 			return errors.Errorf("cannot write to %q; file exists", kubeFile)
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index f15690180f..e625469ede 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.3.1
+Version: 3.3.2
 Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
 Summary: Manage Pods, Containers and Container Images
 License: ASL 2.0
diff --git a/docs/source/markdown/podman-volume-ls.1.md b/docs/source/markdown/podman-volume-ls.1.md
index b562aff613..6c80ec1522 100644
--- a/docs/source/markdown/podman-volume-ls.1.md
+++ b/docs/source/markdown/podman-volume-ls.1.md
@@ -18,13 +18,15 @@ flag. Use the **--quiet** flag to print only the volume names.
 
 Volumes can be filtered by the following attributes:
 
-- dangling
-- driver
-- label
-- name
-- opt
-- scope
-- until
+| **Filter** | **Description**                                                                       |
+| ---------- | ------------------------------------------------------------------------------------- |
+| dangling   | [Dangling] Matches all volumes not referenced by any containers                       |
+| driver     | [Driver] Matches volumes based on their driver                                        |
+| label      | [Key] or [Key=Value] Label assigned to a volume                                       |
+| name       | [Name] Volume name (accepts regex)                                                    |
+| opt        | Matches a storage driver options                                                      |
+| scope      | Filters volume by scope                                                               |
+| until      | Only remove volumes created before given timestamp                                   |
 
 #### **--format**=*format*
 
diff --git a/docs/source/markdown/podman-volume-prune.1.md b/docs/source/markdown/podman-volume-prune.1.md
index b9599c2004..cfdfc1a443 100644
--- a/docs/source/markdown/podman-volume-prune.1.md
+++ b/docs/source/markdown/podman-volume-prune.1.md
@@ -23,8 +23,10 @@ Do not prompt for confirmation.
 
 Filter volumes to be pruned. Volumes can be filtered by the following attributes:
 
-- label
-- until
+| **Filter** | **Description**                                                                       |
+| ---------- | ------------------------------------------------------------------------------------- |
+| label      | [Key] or [Key=Value] Label assigned to a volume                                       |
+| until      | Only remove volumes created before given timestamp                                    |
 
 #### **--help**
 
diff --git a/libpod/events/filters.go b/libpod/events/filters.go
index 4d27e8fc45..d5e2b81f39 100644
--- a/libpod/events/filters.go
+++ b/libpod/events/filters.go
@@ -135,7 +135,7 @@ func generateEventFilters(filters []string, since, until string) (map[string][]E
 	}
 
 	if len(since) > 0 {
-		timeSince, err := util.ParseInputTime(since)
+		timeSince, err := util.ParseInputTime(since, true)
 		if err != nil {
 			return nil, errors.Wrapf(err, "unable to convert since time of %s", since)
 		}
@@ -144,7 +144,7 @@ func generateEventFilters(filters []string, since, until string) (map[string][]E
 	}
 
 	if len(until) > 0 {
-		timeUntil, err := util.ParseInputTime(until)
+		timeUntil, err := util.ParseInputTime(until, false)
 		if err != nil {
 			return nil, errors.Wrapf(err, "unable to convert until time of %s", until)
 		}
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 7006290e9e..a3e0d97541 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -73,13 +73,15 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
 	if err != nil {
 		return errors.Wrapf(err, "failed to parse event filters")
 	}
+
 	var untilTime time.Time
 	if len(options.Until) > 0 {
-		untilTime, err = util.ParseInputTime(options.Until)
+		untilTime, err = util.ParseInputTime(options.Until, false)
 		if err != nil {
 			return err
 		}
 	}
+
 	j, err := sdjournal.NewJournal()
 	if err != nil {
 		return err
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index 952444f2be..e3f0ab8f03 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -53,7 +53,7 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
 		return err
 	}
 	if len(options.Until) > 0 {
-		untilTime, err := util.ParseInputTime(options.Until)
+		untilTime, err := util.ParseInputTime(options.Until, false)
 		if err != nil {
 			return err
 		}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 7eef04ddf1..e41aebb4a8 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -185,7 +185,13 @@ func (r *RootlessCNI) Do(toRun func() error) error {
 				// if there is no symlink exit
 				break
 			}
-			resolvePath = filepath.Join(filepath.Dir(resolvePath), link)
+			if filepath.IsAbs(link) {
+				// link is as an absolute path
+				resolvePath = link
+			} else {
+				// link is as a relative, join it with the previous path
+				resolvePath = filepath.Join(filepath.Dir(resolvePath), link)
+			}
 			if strings.HasPrefix(resolvePath, "/run/") {
 				break
 			}
diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go
index 656e2c627c..50cdb1e653 100644
--- a/pkg/api/handlers/compat/containers_logs.go
+++ b/pkg/api/handlers/compat/containers_logs.go
@@ -63,7 +63,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
 
 	var since time.Time
 	if _, found := r.URL.Query()["since"]; found {
-		since, err = util.ParseInputTime(query.Since)
+		since, err = util.ParseInputTime(query.Since, true)
 		if err != nil {
 			utils.BadRequest(w, "since", query.Since, err)
 			return
@@ -73,7 +73,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
 	var until time.Time
 	if _, found := r.URL.Query()["until"]; found {
 		if query.Until != "0" {
-			until, err = util.ParseInputTime(query.Until)
+			until, err = util.ParseInputTime(query.Until, false)
 			if err != nil {
 				utils.BadRequest(w, "until", query.Until, err)
 				return
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 62b1655acf..974a589a9d 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -56,7 +56,7 @@ func NewConnection(ctx context.Context, uri string) (context.Context, error) {
 	return NewConnectionWithIdentity(ctx, uri, "")
 }
 
-// NewConnection takes a URI as a string and returns a context with the
+// NewConnectionWithIdentity takes a URI as a string and returns a context with the
 // Connection embedded as a value.  This context needs to be passed to each
 // endpoint to work correctly.
 //
@@ -149,6 +149,7 @@ func pingNewConnection(ctx context.Context) error {
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
 
 	if response.StatusCode == http.StatusOK {
 		versionHdr := response.Header.Get("Libpod-API-Version")
@@ -338,7 +339,7 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
 		req.Header.Set(key, val)
 	}
 	// Give the Do three chances in the case of a comm/service hiccup
-	for i := 0; i < 3; i++ {
+	for i := 1; i <= 3; i++ {
 		response, err = c.Client.Do(req) // nolint
 		if err == nil {
 			break
@@ -358,7 +359,7 @@ func FiltersToString(filters map[string][]string) (string, error) {
 	return jsoniter.MarshalToString(lowerCaseKeys)
 }
 
-// IsInformation returns true if the response code is 1xx
+// IsInformational returns true if the response code is 1xx
 func (h *APIResponse) IsInformational() bool {
 	return h.Response.StatusCode/100 == 1
 }
diff --git a/pkg/bindings/containers/archive.go b/pkg/bindings/containers/archive.go
index 52b73662b5..876f5340bd 100644
--- a/pkg/bindings/containers/archive.go
+++ b/pkg/bindings/containers/archive.go
@@ -27,6 +27,7 @@ func Stat(ctx context.Context, nameOrID string, path string) (*entities.Containe
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
 
 	var finalErr error
 	if response.StatusCode == http.StatusNotFound {
@@ -53,7 +54,9 @@ func CopyFromArchive(ctx context.Context, nameOrID string, path string, reader i
 	return CopyFromArchiveWithOptions(ctx, nameOrID, path, reader, nil)
 }
 
-// CopyFromArchiveWithOptions FIXME: remove this function and make CopyFromArchive accept the option as the last parameter in podman 4.0
+// CopyFromArchiveWithOptions copy files into container
+//
+// FIXME: remove this function and make CopyFromArchive accept the option as the last parameter in podman 4.0
 func CopyFromArchiveWithOptions(ctx context.Context, nameOrID string, path string, reader io.Reader, options *CopyOptions) (entities.ContainerCopyFunc, error) {
 	conn, err := bindings.GetClient(ctx)
 	if err != nil {
@@ -72,6 +75,7 @@ func CopyFromArchiveWithOptions(ctx context.Context, nameOrID string, path strin
 		if err != nil {
 			return err
 		}
+
 		if response.StatusCode != http.StatusOK {
 			return errors.New(response.Status)
 		}
@@ -79,6 +83,7 @@ func CopyFromArchiveWithOptions(ctx context.Context, nameOrID string, path strin
 	}, nil
 }
 
+// CopyToArchive copy files from container
 func CopyToArchive(ctx context.Context, nameOrID string, path string, writer io.Writer) (entities.ContainerCopyFunc, error) {
 	conn, err := bindings.GetClient(ctx)
 	if err != nil {
@@ -91,11 +96,14 @@ func CopyToArchive(ctx context.Context, nameOrID string, path string, writer io.
 	if err != nil {
 		return nil, err
 	}
+
 	if response.StatusCode != http.StatusOK {
+		defer response.Body.Close()
 		return nil, response.Process(nil)
 	}
 
 	return func() error {
+		defer response.Body.Close()
 		_, err := io.Copy(writer, response.Body)
 		return err
 	}, nil
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
index 01c14d350a..6efbcb57b9 100644
--- a/pkg/bindings/containers/attach.go
+++ b/pkg/bindings/containers/attach.go
@@ -134,7 +134,9 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
 	if err != nil {
 		return err
 	}
+
 	if !(response.IsSuccess() || response.IsInformational()) {
+		defer response.Body.Close()
 		return response.Process(nil)
 	}
 
@@ -207,7 +209,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
 			}
 		}
 	} else {
-		logrus.Debugf("Copying standard streams of container in non-terminal mode")
+		logrus.Debugf("Copying standard streams of container %q in non-terminal mode", ctnr.ID)
 		for {
 			// Read multiplexed channels and write to appropriate stream
 			fd, l, err := DemuxHeader(socket, buffer)
@@ -324,6 +326,8 @@ func resizeTTY(ctx context.Context, endpoint string, height *int, width *int) er
 	if err != nil {
 		return err
 	}
+	defer rsp.Body.Close()
+
 	return rsp.Process(nil)
 }
 
@@ -407,6 +411,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
 	if err != nil {
 		return err
 	}
+	defer resp.Body.Close()
 
 	respStruct := new(define.InspectExecSession)
 	if err := resp.Process(respStruct); err != nil {
@@ -477,6 +482,8 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	if !(response.IsSuccess() || response.IsInformational()) {
 		return response.Process(nil)
 	}
diff --git a/pkg/bindings/containers/checkpoint.go b/pkg/bindings/containers/checkpoint.go
index 440bf707d6..7f7080f13b 100644
--- a/pkg/bindings/containers/checkpoint.go
+++ b/pkg/bindings/containers/checkpoint.go
@@ -27,6 +27,8 @@ func Checkpoint(ctx context.Context, nameOrID string, options *CheckpointOptions
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -54,5 +56,7 @@ func Restore(ctx context.Context, nameOrID string, options *RestoreOptions) (*en
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
diff --git a/pkg/bindings/containers/commit.go b/pkg/bindings/containers/commit.go
index 8ae61322e0..a4adebb1f3 100644
--- a/pkg/bindings/containers/commit.go
+++ b/pkg/bindings/containers/commit.go
@@ -28,5 +28,7 @@ func Commit(ctx context.Context, nameOrID string, options *CommitOptions) (handl
 	if err != nil {
 		return id, err
 	}
+	defer response.Body.Close()
+
 	return id, response.Process(&id)
 }
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index 86304f392a..db919669af 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -42,6 +42,8 @@ func List(ctx context.Context, options *ListOptions) ([]entities.ListContainer,
 	if err != nil {
 		return containers, err
 	}
+	defer response.Body.Close()
+
 	return containers, response.Process(&containers)
 }
 
@@ -66,6 +68,8 @@ func Prune(ctx context.Context, options *PruneOptions) ([]*reports.PruneReport,
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return reports, response.Process(&reports)
 }
 
@@ -90,6 +94,8 @@ func Remove(ctx context.Context, nameOrID string, options *RemoveOptions) error
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -113,6 +119,8 @@ func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) (*de
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	inspect := define.InspectContainerData{}
 	return &inspect, response.Process(&inspect)
 }
@@ -136,6 +144,8 @@ func Kill(ctx context.Context, nameOrID string, options *KillOptions) error {
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -154,6 +164,8 @@ func Pause(ctx context.Context, nameOrID string, options *PauseOptions) error {
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -176,6 +188,8 @@ func Restart(ctx context.Context, nameOrID string, options *RestartOptions) erro
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -199,6 +213,8 @@ func Start(ctx context.Context, nameOrID string, options *StartOptions) error {
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -228,6 +244,7 @@ func Stats(ctx context.Context, containers []string, options *StatsOptions) (cha
 
 	go func() {
 		defer close(statsChan)
+		defer response.Body.Close()
 
 		dec := json.NewDecoder(response.Body)
 		doStream := true
@@ -242,6 +259,7 @@ func Stats(ctx context.Context, containers []string, options *StatsOptions) (cha
 		default:
 			// fall through and do some work
 		}
+
 		var report entities.ContainerStatsReport
 		if err := dec.Decode(&report); err != nil {
 			report = entities.ContainerStatsReport{Error: err}
@@ -276,6 +294,7 @@ func Top(ctx context.Context, nameOrID string, options *TopOptions) ([]string, e
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
 
 	body := handlers.ContainerTopOKBody{}
 	if err = response.Process(&body); err != nil {
@@ -308,6 +327,8 @@ func Unpause(ctx context.Context, nameOrID string, options *UnpauseOptions) erro
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -331,6 +352,8 @@ func Wait(ctx context.Context, nameOrID string, options *WaitOptions) (int32, er
 	if err != nil {
 		return exitCode, err
 	}
+	defer response.Body.Close()
+
 	return exitCode, response.Process(&exitCode)
 }
 
@@ -350,6 +373,8 @@ func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool,
 	if err != nil {
 		return false, err
 	}
+	defer response.Body.Close()
+
 	return response.IsSuccess(), nil
 }
 
@@ -371,6 +396,8 @@ func Stop(ctx context.Context, nameOrID string, options *StopOptions) error {
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -390,6 +417,8 @@ func Export(ctx context.Context, nameOrID string, w io.Writer, options *ExportOp
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	if response.StatusCode/100 == 2 {
 		_, err = io.Copy(w, response.Body)
 		return err
@@ -413,6 +442,8 @@ func ContainerInit(ctx context.Context, nameOrID string, options *InitOptions) e
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	if response.StatusCode == http.StatusNotModified {
 		return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has already been created in runtime", nameOrID)
 	}
@@ -432,5 +463,7 @@ func ShouldRestart(ctx context.Context, nameOrID string, options *ShouldRestartO
 	if err != nil {
 		return false, err
 	}
+	defer response.Body.Close()
+
 	return response.IsSuccess(), nil
 }
diff --git a/pkg/bindings/containers/create.go b/pkg/bindings/containers/create.go
index 3efa9643de..c0b9538a6c 100644
--- a/pkg/bindings/containers/create.go
+++ b/pkg/bindings/containers/create.go
@@ -30,5 +30,7 @@ func CreateWithSpec(ctx context.Context, s *specgen.SpecGenerator, options *Crea
 	if err != nil {
 		return ccr, err
 	}
+	defer response.Body.Close()
+
 	return ccr, response.Process(&ccr)
 }
diff --git a/pkg/bindings/containers/diff.go b/pkg/bindings/containers/diff.go
index 7d20ae5307..e4ec49809a 100644
--- a/pkg/bindings/containers/diff.go
+++ b/pkg/bindings/containers/diff.go
@@ -26,6 +26,8 @@ func Diff(ctx context.Context, nameOrID string, options *DiffOptions) ([]archive
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	var changes []archive.Change
 	return changes, response.Process(&changes)
 }
diff --git a/pkg/bindings/containers/exec.go b/pkg/bindings/containers/exec.go
index 5ae6d1d712..12b31aba35 100644
--- a/pkg/bindings/containers/exec.go
+++ b/pkg/bindings/containers/exec.go
@@ -39,6 +39,7 @@ func ExecCreate(ctx context.Context, nameOrID string, config *handlers.ExecCreat
 	if err != nil {
 		return "", err
 	}
+	defer resp.Body.Close()
 
 	respStruct := new(handlers.ExecCreateResponse)
 	if err := resp.Process(respStruct); err != nil {
@@ -66,6 +67,7 @@ func ExecInspect(ctx context.Context, sessionID string, options *ExecInspectOpti
 	if err != nil {
 		return nil, err
 	}
+	defer resp.Body.Close()
 
 	respStruct := new(define.InspectExecSession)
 	if err := resp.Process(respStruct); err != nil {
@@ -103,6 +105,7 @@ func ExecStart(ctx context.Context, sessionID string, options *ExecStartOptions)
 	if err != nil {
 		return err
 	}
+	defer resp.Body.Close()
 
 	return resp.Process(nil)
 }
diff --git a/pkg/bindings/containers/healthcheck.go b/pkg/bindings/containers/healthcheck.go
index d6b7216152..0e65a5a464 100644
--- a/pkg/bindings/containers/healthcheck.go
+++ b/pkg/bindings/containers/healthcheck.go
@@ -26,5 +26,7 @@ func RunHealthCheck(ctx context.Context, nameOrID string, options *HealthCheckOp
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &status, response.Process(&status)
 }
diff --git a/pkg/bindings/containers/logs.go b/pkg/bindings/containers/logs.go
index a3100c697e..67db944872 100644
--- a/pkg/bindings/containers/logs.go
+++ b/pkg/bindings/containers/logs.go
@@ -33,6 +33,7 @@ func Logs(ctx context.Context, nameOrID string, options *LogOptions, stdoutChan,
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
 
 	buffer := make([]byte, 1024)
 	for {
diff --git a/pkg/bindings/containers/mount.go b/pkg/bindings/containers/mount.go
index bb5c3bd67a..c07998fd39 100644
--- a/pkg/bindings/containers/mount.go
+++ b/pkg/bindings/containers/mount.go
@@ -25,6 +25,8 @@ func Mount(ctx context.Context, nameOrID string, options *MountOptions) (string,
 	if err != nil {
 		return path, err
 	}
+	defer response.Body.Close()
+
 	return path, response.Process(&path)
 }
 
@@ -43,6 +45,8 @@ func Unmount(ctx context.Context, nameOrID string, options *UnmountOptions) erro
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -61,5 +65,7 @@ func GetMountedContainerPaths(ctx context.Context, options *MountedContainerPath
 	if err != nil {
 		return mounts, err
 	}
+	defer response.Body.Close()
+
 	return mounts, response.Process(&mounts)
 }
diff --git a/pkg/bindings/containers/rename.go b/pkg/bindings/containers/rename.go
index 60d7fda73a..172d7838a3 100644
--- a/pkg/bindings/containers/rename.go
+++ b/pkg/bindings/containers/rename.go
@@ -24,5 +24,7 @@ func Rename(ctx context.Context, nameOrID string, options *RenameOptions) error
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go
index 3339062a58..9c311d9120 100644
--- a/pkg/bindings/errors.go
+++ b/pkg/bindings/errors.go
@@ -20,6 +20,8 @@ func handleError(data []byte) error {
 	return e
 }
 
+// Process drains the response body, and processes the HTTP status code
+// Note: Closing the response.Body is left to the caller
 func (h APIResponse) Process(unmarshalInto interface{}) error {
 	data, err := ioutil.ReadAll(h.Response.Body)
 	if err != nil {
diff --git a/pkg/bindings/generate/generate.go b/pkg/bindings/generate/generate.go
index 7c904a6a8a..7429565155 100644
--- a/pkg/bindings/generate/generate.go
+++ b/pkg/bindings/generate/generate.go
@@ -26,10 +26,15 @@ func Systemd(ctx context.Context, nameOrID string, options *SystemdOptions) (*en
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	report := &entities.GenerateSystemdReport{}
 	return report, response.Process(&report.Units)
 }
 
+// Kube generate Kubernetes YAML (v1 specification)
+//
+// Note: Caller is responsible for closing returned reader
 func Kube(ctx context.Context, nameOrIDs []string, options *KubeOptions) (*entities.GenerateKubeReport, error) {
 	if options == nil {
 		options = new(KubeOptions)
diff --git a/pkg/bindings/images/diff.go b/pkg/bindings/images/diff.go
index 79b0df8c99..671b73089a 100644
--- a/pkg/bindings/images/diff.go
+++ b/pkg/bindings/images/diff.go
@@ -23,6 +23,8 @@ func Diff(ctx context.Context, nameOrID string, options *DiffOptions) ([]archive
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	var changes []archive.Change
 	return changes, response.Process(&changes)
 }
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index 8680d6baa9..959481e0dc 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -27,6 +27,8 @@ func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool,
 	if err != nil {
 		return false, err
 	}
+	defer response.Body.Close()
+
 	return response.IsSuccess(), nil
 }
 
@@ -49,6 +51,8 @@ func List(ctx context.Context, options *ListOptions) ([]*entities.ImageSummary,
 	if err != nil {
 		return imageSummary, err
 	}
+	defer response.Body.Close()
+
 	return imageSummary, response.Process(&imageSummary)
 }
 
@@ -71,6 +75,8 @@ func GetImage(ctx context.Context, nameOrID string, options *GetOptions) (*entit
 	if err != nil {
 		return &inspectedData, err
 	}
+	defer response.Body.Close()
+
 	return &inspectedData, response.Process(&inspectedData)
 }
 
@@ -92,6 +98,8 @@ func Tree(ctx context.Context, nameOrID string, options *TreeOptions) (*entities
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -110,6 +118,8 @@ func History(ctx context.Context, nameOrID string, options *HistoryOptions) ([]*
 	if err != nil {
 		return history, err
 	}
+	defer response.Body.Close()
+
 	return history, response.Process(&history)
 }
 
@@ -123,6 +133,8 @@ func Load(ctx context.Context, r io.Reader) (*entities.ImageLoadReport, error) {
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -147,6 +159,7 @@ func Export(ctx context.Context, nameOrIDs []string, w io.Writer, options *Expor
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
 
 	if response.StatusCode/100 == 2 || response.StatusCode/100 == 3 {
 		_, err = io.Copy(w, response.Body)
@@ -176,8 +189,9 @@ func Prune(ctx context.Context, options *PruneOptions) ([]*reports.PruneReport,
 	if err != nil {
 		return deleted, err
 	}
-	err = response.Process(&deleted)
-	return deleted, err
+	defer response.Body.Close()
+
+	return deleted, response.Process(&deleted)
 }
 
 // Tag adds an additional name to locally-stored image. Both the tag and repo parameters are required.
@@ -197,6 +211,8 @@ func Tag(ctx context.Context, nameOrID, tag, repo string, options *TagOptions) e
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -217,10 +233,12 @@ func Untag(ctx context.Context, nameOrID, tag, repo string, options *UntagOption
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
-// Imports adds the given image to the local image store.  This can be done by file and the given reader
+// Import adds the given image to the local image store.  This can be done by file and the given reader
 // or via the url parameter.  Additional metadata can be associated with the image by using the changes and
 // message parameters.  The image can also be tagged given a reference. One of url OR r must be provided.
 func Import(ctx context.Context, r io.Reader, options *ImportOptions) (*entities.ImageImportReport, error) {
@@ -243,6 +261,8 @@ func Import(ctx context.Context, r io.Reader, options *ImportOptions) (*entities
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -269,8 +289,8 @@ func Push(ctx context.Context, source string, destination string, options *PushO
 	if err != nil {
 		return err
 	}
-	//SkipTLSVerify is special.  We need to delete the param added by
-	//toparams and change the key and flip the bool
+	// SkipTLSVerify is special.  We need to delete the param added by
+	// toparams and change the key and flip the bool
 	if options.SkipTLSVerify != nil {
 		params.Del("SkipTLSVerify")
 		params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
@@ -282,6 +302,7 @@ func Push(ctx context.Context, source string, destination string, options *PushO
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
 
 	return response.Process(err)
 }
@@ -317,6 +338,7 @@ func Search(ctx context.Context, term string, options *SearchOptions) ([]entitie
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
 
 	results := []entities.ImageSearchReport{}
 	if err := response.Process(&results); err != nil {
diff --git a/pkg/bindings/images/rm.go b/pkg/bindings/images/rm.go
index e45e583f4c..461eb77296 100644
--- a/pkg/bindings/images/rm.go
+++ b/pkg/bindings/images/rm.go
@@ -36,6 +36,8 @@ func Remove(ctx context.Context, images []string, options *RemoveOptions) (*enti
 	if err != nil {
 		return nil, []error{err}
 	}
+	defer response.Body.Close()
+
 	if err := response.Process(&report); err != nil {
 		return nil, []error{err}
 	}
diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go
index 268ce3b19f..6aa4961f1d 100644
--- a/pkg/bindings/manifests/manifests.go
+++ b/pkg/bindings/manifests/manifests.go
@@ -46,10 +46,12 @@ func Create(ctx context.Context, names, images []string, options *CreateOptions)
 	if err != nil {
 		return "", err
 	}
+	defer response.Body.Close()
+
 	return idr.ID, response.Process(&idr)
 }
 
-// Exists returns true if a given maifest list exists
+// Exists returns true if a given manifest list exists
 func Exists(ctx context.Context, name string, options *ExistsOptions) (bool, error) {
 	conn, err := bindings.GetClient(ctx)
 	if err != nil {
@@ -59,6 +61,8 @@ func Exists(ctx context.Context, name string, options *ExistsOptions) (bool, err
 	if err != nil {
 		return false, err
 	}
+	defer response.Body.Close()
+
 	return response.IsSuccess(), nil
 }
 
@@ -77,6 +81,8 @@ func Inspect(ctx context.Context, name string, options *InspectOptions) (*manife
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &list, response.Process(&list)
 }
 
@@ -100,6 +106,8 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error)
 	if err != nil {
 		return "", err
 	}
+	defer response.Body.Close()
+
 	return idr.ID, response.Process(&idr)
 }
 
@@ -121,6 +129,8 @@ func Remove(ctx context.Context, name, digest string, options *RemoveOptions) (s
 	if err != nil {
 		return "", err
 	}
+	defer response.Body.Close()
+
 	return idr.ID, response.Process(&idr)
 }
 
@@ -145,18 +155,20 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt
 	if err != nil {
 		return "", err
 	}
-	//SkipTLSVerify is special.  We need to delete the param added by
-	//toparams and change the key and flip the bool
+	// SkipTLSVerify is special.  We need to delete the param added by
+	// toparams and change the key and flip the bool
 	if options.SkipTLSVerify != nil {
 		params.Del("SkipTLSVerify")
 		params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
 	}
 	params.Set("image", name)
 	params.Set("destination", destination)
-	_, err = conn.DoRequest(nil, http.MethodPost, "/manifests/%s/push", params, nil, name)
+	response, err := conn.DoRequest(nil, http.MethodPost, "/manifests/%s/push", params, nil, name)
 	if err != nil {
 		return "", err
 	}
+	defer response.Body.Close()
+
 	return idr.ID, err
 }
 
@@ -179,5 +191,6 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt
 //	if err != nil {
 //		return "", err
 //	}
+//  defer response.Body.Close()
 //	return idr.ID, response.Process(&idr)
 //}
diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go
index 17451c273d..59207aa8d0 100644
--- a/pkg/bindings/network/network.go
+++ b/pkg/bindings/network/network.go
@@ -34,6 +34,8 @@ func Create(ctx context.Context, options *CreateOptions) (*entities.NetworkCreat
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -53,6 +55,8 @@ func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) ([]e
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return reports, response.Process(&reports[0])
 }
 
@@ -76,6 +80,8 @@ func Remove(ctx context.Context, nameOrID string, options *RemoveOptions) ([]*en
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return reports, response.Process(&reports)
 }
 
@@ -99,6 +105,8 @@ func List(ctx context.Context, options *ListOptions) ([]*entities.NetworkListRep
 	if err != nil {
 		return netList, err
 	}
+	defer response.Body.Close()
+
 	return netList, response.Process(&netList)
 }
 
@@ -133,6 +141,8 @@ func Disconnect(ctx context.Context, networkName string, ContainerNameOrID strin
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -166,6 +176,8 @@ func Connect(ctx context.Context, networkName string, ContainerNameOrID string,
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -179,6 +191,8 @@ func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool,
 	if err != nil {
 		return false, err
 	}
+	defer response.Body.Close()
+
 	return response.IsSuccess(), nil
 }
 
@@ -203,5 +217,7 @@ func Prune(ctx context.Context, options *PruneOptions) ([]*entities.NetworkPrune
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return prunedNetworks, response.Process(&prunedNetworks)
 }
diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go
index 4b735c8217..8451cd5335 100644
--- a/pkg/bindings/play/play.go
+++ b/pkg/bindings/play/play.go
@@ -48,6 +48,8 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	if err := response.Process(&report); err != nil {
 		return nil, err
 	}
diff --git a/pkg/bindings/pods/pods.go b/pkg/bindings/pods/pods.go
index eb7b273cf4..9d3ff322ec 100644
--- a/pkg/bindings/pods/pods.go
+++ b/pkg/bindings/pods/pods.go
@@ -34,6 +34,8 @@ func CreatePodFromSpec(ctx context.Context, s *specgen.PodSpecGenerator, options
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &pcr, response.Process(&pcr)
 }
 
@@ -47,6 +49,8 @@ func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool,
 	if err != nil {
 		return false, err
 	}
+	defer response.Body.Close()
+
 	return response.IsSuccess(), nil
 }
 
@@ -67,6 +71,8 @@ func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) (*en
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -91,6 +97,8 @@ func Kill(ctx context.Context, nameOrID string, options *KillOptions) (*entities
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -109,6 +117,8 @@ func Pause(ctx context.Context, nameOrID string, options *PauseOptions) (*entiti
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -128,6 +138,8 @@ func Prune(ctx context.Context, options *PruneOptions) ([]*entities.PodPruneRepo
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return reports, response.Process(&reports)
 }
 
@@ -152,6 +164,8 @@ func List(ctx context.Context, options *ListOptions) ([]*entities.ListPodsReport
 	if err != nil {
 		return podsReports, err
 	}
+	defer response.Body.Close()
+
 	return podsReports, response.Process(&podsReports)
 }
 
@@ -170,6 +184,8 @@ func Restart(ctx context.Context, nameOrID string, options *RestartOptions) (*en
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -192,6 +208,8 @@ func Remove(ctx context.Context, nameOrID string, options *RemoveOptions) (*enti
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -210,6 +228,8 @@ func Start(ctx context.Context, nameOrID string, options *StartOptions) (*entiti
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	if response.StatusCode == http.StatusNotModified {
 		report.Id = nameOrID
 		return &report, nil
@@ -236,6 +256,8 @@ func Stop(ctx context.Context, nameOrID string, options *StopOptions) (*entities
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	if response.StatusCode == http.StatusNotModified {
 		report.Id = nameOrID
 		return &report, nil
@@ -261,6 +283,7 @@ func Top(ctx context.Context, nameOrID string, options *TopOptions) ([]string, e
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
 
 	body := handlers.PodTopOKBody{}
 	if err = response.Process(&body); err != nil {
@@ -293,6 +316,8 @@ func Unpause(ctx context.Context, nameOrID string, options *UnpauseOptions) (*en
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -318,5 +343,7 @@ func Stats(ctx context.Context, namesOrIDs []string, options *StatsOptions) ([]*
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return reports, response.Process(&reports)
 }
diff --git a/pkg/bindings/secrets/secrets.go b/pkg/bindings/secrets/secrets.go
index 091d38e56c..b741d3e5c4 100644
--- a/pkg/bindings/secrets/secrets.go
+++ b/pkg/bindings/secrets/secrets.go
@@ -22,6 +22,8 @@ func List(ctx context.Context, options *ListOptions) ([]*entities.SecretInfoRepo
 	if err != nil {
 		return secrs, err
 	}
+	defer response.Body.Close()
+
 	return secrs, response.Process(&secrs)
 }
 
@@ -38,6 +40,8 @@ func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) (*en
 	if err != nil {
 		return inspect, err
 	}
+	defer response.Body.Close()
+
 	return inspect, response.Process(&inspect)
 }
 
@@ -52,6 +56,8 @@ func Remove(ctx context.Context, nameOrID string) error {
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -74,5 +80,7 @@ func Create(ctx context.Context, reader io.Reader, options *CreateOptions) (*ent
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return create, response.Process(&create)
 }
diff --git a/pkg/bindings/system/info.go b/pkg/bindings/system/info.go
index 244f9643e2..8a307a4ca9 100644
--- a/pkg/bindings/system/info.go
+++ b/pkg/bindings/system/info.go
@@ -9,12 +9,7 @@ import (
 )
 
 // Info returns information about the libpod environment and its stores
-func Info(ctx context.Context, options *InfoOptions) (*define.Info, error) {
-	if options == nil {
-		options = new(InfoOptions)
-	}
-	_ = options
-	info := define.Info{}
+func Info(ctx context.Context, _ *InfoOptions) (*define.Info, error) {
 	conn, err := bindings.GetClient(ctx)
 	if err != nil {
 		return nil, err
@@ -23,5 +18,8 @@ func Info(ctx context.Context, options *InfoOptions) (*define.Info, error) {
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
+	info := define.Info{}
 	return &info, response.Process(&info)
 }
diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go
index 310bcef15a..719cde52e3 100644
--- a/pkg/bindings/system/system.go
+++ b/pkg/bindings/system/system.go
@@ -31,6 +31,8 @@ func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	if cancelChan != nil {
 		go func() {
 			<-cancelChan
@@ -75,6 +77,8 @@ func Prune(ctx context.Context, options *PruneOptions) (*entities.SystemPruneRep
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
 
@@ -101,6 +105,7 @@ func Version(ctx context.Context, options *VersionOptions) (*entities.SystemVers
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
 
 	if err = response.Process(&component); err != nil {
 		return nil, err
@@ -141,5 +146,7 @@ func DiskUsage(ctx context.Context, options *DiskOptions) (*entities.SystemDfRep
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &report, response.Process(&report)
 }
diff --git a/pkg/bindings/volumes/volumes.go b/pkg/bindings/volumes/volumes.go
index fb58a1d1f5..56cf13ade9 100644
--- a/pkg/bindings/volumes/volumes.go
+++ b/pkg/bindings/volumes/volumes.go
@@ -33,6 +33,8 @@ func Create(ctx context.Context, config entities.VolumeCreateOptions, options *C
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return &v, response.Process(&v)
 }
 
@@ -53,6 +55,8 @@ func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) (*en
 	if err != nil {
 		return &inspect, err
 	}
+	defer response.Body.Close()
+
 	return &inspect, response.Process(&inspect)
 }
 
@@ -74,6 +78,8 @@ func List(ctx context.Context, options *ListOptions) ([]*entities.VolumeListRepo
 	if err != nil {
 		return vols, err
 	}
+	defer response.Body.Close()
+
 	return vols, response.Process(&vols)
 }
 
@@ -94,6 +100,8 @@ func Prune(ctx context.Context, options *PruneOptions) ([]*reports.PruneReport,
 	if err != nil {
 		return nil, err
 	}
+	defer response.Body.Close()
+
 	return pruned, response.Process(&pruned)
 }
 
@@ -112,6 +120,8 @@ func Remove(ctx context.Context, nameOrID string, options *RemoveOptions) error
 	if err != nil {
 		return err
 	}
+	defer response.Body.Close()
+
 	return response.Process(nil)
 }
 
@@ -125,5 +135,7 @@ func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool,
 	if err != nil {
 		return false, err
 	}
+	defer response.Body.Close()
+
 	return response.IsSuccess(), nil
 }
diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go
index 3ec713edfe..8a437061f5 100644
--- a/pkg/domain/entities/generate.go
+++ b/pkg/domain/entities/generate.go
@@ -35,6 +35,8 @@ type GenerateKubeOptions struct {
 }
 
 // GenerateKubeReport
+//
+// FIXME: Podman4.0 should change io.Reader to io.ReaderCloser
 type GenerateKubeReport struct {
 	// Reader - the io.Reader to reader the generated YAML file.
 	Reader io.Reader
diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go
index 0e768b30bc..3d3cd52be4 100644
--- a/pkg/domain/infra/tunnel/generate.go
+++ b/pkg/domain/infra/tunnel/generate.go
@@ -16,6 +16,9 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string,
 	return generate.Systemd(ic.ClientCtx, nameOrID, options)
 }
 
+// GenerateKube Kubernetes YAML (v1 specification) for nameOrIDs
+//
+// Note: Caller is responsible for closing returned Reader
 func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, opts entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
 	options := new(generate.KubeOptions).WithService(opts.Service)
 	return generate.Kube(ic.ClientCtx, nameOrIDs, options)
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 646c84aba3..ac70357c6c 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -244,6 +244,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
 		qemuSocketConn net.Conn
 		wait           time.Duration = time.Millisecond * 500
 	)
+
 	if err := v.startHostNetworking(); err != nil {
 		return errors.Errorf("unable to start host networking: %q", err)
 	}
@@ -264,7 +265,11 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
 	if err != nil {
 		return err
 	}
-
+	// If the qemusocketpath exists and the vm is off/down, we should rm
+	// it before the dial as to avoid a segv
+	if err := os.Remove(qemuSocketPath); err != nil && !errors.Is(err, os.ErrNotExist) {
+		logrus.Warn(err)
+	}
 	for i := 0; i < 6; i++ {
 		qemuSocketConn, err = net.Dial("unix", qemuSocketPath)
 		if err == nil {
@@ -352,7 +357,7 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
 	if _, err = qmpMonitor.Run(input); err != nil {
 		return err
 	}
-	_, pidFile, err := v.getSocketandPid()
+	qemuSocketFile, pidFile, err := v.getSocketandPid()
 	if err != nil {
 		return err
 	}
@@ -373,7 +378,16 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
 	if p == nil && err != nil {
 		return err
 	}
-	return p.Kill()
+	// Kill the process
+	if err := p.Kill(); err != nil {
+		return err
+	}
+	// Remove the pidfile
+	if err := os.Remove(pidFile); err != nil && !errors.Is(err, os.ErrNotExist) {
+		logrus.Warn(err)
+	}
+	// Remove socket
+	return os.Remove(qemuSocketFile)
 }
 
 // NewQMPMonitor creates the monitor subsection of our vm
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 774590f44f..37a00c25c5 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -520,7 +520,7 @@ func WriteStorageConfigFile(storageOpts *stypes.StoreOptions, storageConf string
 // ParseInputTime takes the users input and to determine if it is valid and
 // returns a time format and error.  The input is compared to known time formats
 // or a duration which implies no-duration
-func ParseInputTime(inputTime string) (time.Time, error) {
+func ParseInputTime(inputTime string, since bool) (time.Time, error) {
 	timeFormats := []string{time.RFC3339Nano, time.RFC3339, "2006-01-02T15:04:05", "2006-01-02T15:04:05.999999999",
 		"2006-01-02Z07:00", "2006-01-02"}
 	// iterate the supported time formats
@@ -542,7 +542,10 @@ func ParseInputTime(inputTime string) (time.Time, error) {
 	if err != nil {
 		return time.Time{}, errors.Errorf("unable to interpret time value")
 	}
-	return time.Now().Add(-duration), nil
+	if since {
+		return time.Now().Add(-duration), nil
+	}
+	return time.Now().Add(duration), nil
 }
 
 // OpenExclusiveFile opens a file for writing and ensure it doesn't already exist
diff --git a/utils/utils_supported.go b/utils/utils_supported.go
index 8668e3fba8..ebc870d267 100644
--- a/utils/utils_supported.go
+++ b/utils/utils_supported.go
@@ -36,6 +36,7 @@ func RunUnderSystemdScope(pid int, slice string, unitName string) error {
 			return err
 		}
 	}
+	defer conn.Close()
 	properties = append(properties, systemdDbus.PropSlice(slice))
 	properties = append(properties, newProp("PIDs", []uint32{uint32(pid)}))
 	properties = append(properties, newProp("Delegate", true))
@@ -54,7 +55,6 @@ func RunUnderSystemdScope(pid int, slice string, unitName string) error {
 		}
 		return err
 	}
-	defer conn.Close()
 
 	// Block until job is started
 	<-ch
diff --git a/version/version.go b/version/version.go
index dc1a183d1a..5d6c236441 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.3.1-dev")
+var Version = semver.MustParse("3.3.2-dev")
 
 // See https://docs.docker.com/engine/api/v1.40/
 // libpod compat handlers are expected to honor docker API versions


Test patch:
diff --git a/pkg/bindings/test/attach_test.go b/pkg/bindings/test/attach_test.go
index fbdf18d44d..5c3ec48e4f 100644
--- a/pkg/bindings/test/attach_test.go
+++ b/pkg/bindings/test/attach_test.go
@@ -81,10 +81,9 @@ var _ = Describe("Podman containers attach", func() {
 		tickTock := time.NewTimer(2 * time.Second)
 		go func() {
 			<-tickTock.C
-			timeout := uint(5)
-			err := containers.Stop(bt.conn, ctnr.ID, new(containers.StopOptions).WithTimeout(timeout))
+			err := containers.Stop(bt.conn, ctnr.ID, new(containers.StopOptions).WithTimeout(uint(5)))
 			if err != nil {
-				GinkgoWriter.Write([]byte(err.Error()))
+				fmt.Fprint(GinkgoWriter, err.Error())
 			}
 		}()
 
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index 9bac4b620b..91ebe21fca 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -8,6 +8,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"strings"
+	"time"
 
 	"github.com/containers/podman/v3/libpod/define"
 	. "github.com/containers/podman/v3/pkg/bindings"
@@ -150,11 +151,21 @@ func createTempDirInTempDir() (string, error) {
 }
 
 func (b *bindingTest) startAPIService() *gexec.Session {
-	var (
-		cmd []string
-	)
-	cmd = append(cmd, "--log-level=debug", "--events-backend=file", "system", "service", "--timeout=0", b.sock)
-	return b.runPodman(cmd)
+	cmd := []string{"--log-level=debug", "--events-backend=file", "system", "service", "--timeout=0", b.sock}
+	session := b.runPodman(cmd)
+
+	sock := strings.TrimPrefix(b.sock, "unix://")
+	for i := 0; i < 10; i++ {
+		if _, err := os.Stat(sock); err != nil {
+			if !os.IsNotExist(err) {
+				break
+			}
+			time.Sleep(time.Second)
+			continue
+		}
+		break
+	}
+	return session
 }
 
 func (b *bindingTest) cleanup() {
diff --git a/pkg/bindings/test/resource_test.go b/pkg/bindings/test/resource_test.go
new file mode 100644
index 0000000000..b12d1ccd68
--- /dev/null
+++ b/pkg/bindings/test/resource_test.go
@@ -0,0 +1,116 @@
+package test_bindings
+
+import (
+	"context"
+	"fmt"
+	"io/fs"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"reflect"
+	"strconv"
+	"syscall"
+
+	"github.com/containers/podman/v3/pkg/bindings"
+	"github.com/containers/podman/v3/pkg/bindings/containers"
+	"github.com/containers/podman/v3/pkg/bindings/images"
+	"github.com/containers/podman/v3/pkg/bindings/pods"
+	"github.com/containers/podman/v3/pkg/bindings/system"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	. "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Verify Podman resources", func() {
+	var (
+		bt *bindingTest
+		s  *Session
+	)
+
+	BeforeEach(func() {
+		bt = newBindingTest()
+		s = bt.startAPIService()
+		err := bt.NewConnection()
+		Expect(err).ShouldNot(HaveOccurred())
+	})
+
+	AfterEach(func() {
+		s.Kill()
+		bt.cleanup()
+	})
+
+	It("no leaked connections", func() {
+		conn, err := bindings.NewConnection(context.Background(), bt.sock)
+		Expect(err).ShouldNot(HaveOccurred())
+
+		// Record details on open file descriptors before using API
+		buffer := lsof()
+
+		// Record open fd from /proc
+		start, err := readProc()
+		Expect(err).ShouldNot(HaveOccurred())
+
+		// Run some operations
+		_, err = system.Info(conn, nil)
+		Expect(err).ShouldNot(HaveOccurred())
+		_, err = images.List(conn, nil)
+		Expect(err).ShouldNot(HaveOccurred())
+		_, err = containers.List(conn, nil)
+		Expect(err).ShouldNot(HaveOccurred())
+		_, err = pods.List(conn, nil)
+		Expect(err).ShouldNot(HaveOccurred())
+
+		podman, _ := bindings.GetClient(conn)
+		podman.Client.CloseIdleConnections()
+
+		// Record open fd from /proc
+		finished, err := readProc()
+		Expect(err).ShouldNot(HaveOccurred())
+		if !reflect.DeepEqual(finished, start) {
+			fmt.Fprintf(GinkgoWriter, "Open FDs:\nlsof Before:\n%s\n", buffer)
+
+			// Record details on open file descriptors after using API
+			buffer := lsof()
+			fmt.Fprintf(GinkgoWriter, "lsof After:\n%s\n", buffer)
+
+			// We know test has failed. Easier to let ginkgo format output.
+			Expect(finished).Should(Equal(start))
+		}
+	})
+})
+
+func lsof() string {
+	lsof := exec.Command("lsof", "+E", "-p", strconv.Itoa(os.Getpid()))
+	buffer, err := lsof.Output()
+	Expect(err).ShouldNot(HaveOccurred())
+	return string(buffer)
+}
+
+func readProc() ([]string, error) {
+	syscall.Sync()
+
+	names := make([]string, 0)
+	err := filepath.WalkDir(fmt.Sprintf("/proc/%d/fd", os.Getpid()),
+		func(path string, d fs.DirEntry, err error) error {
+			name := path + " -> "
+
+			switch {
+			case d.IsDir():
+				return nil
+			case err != nil:
+				name += err.Error()
+			case d.Type()&fs.ModeSymlink != 0:
+				n, err := os.Readlink(path)
+				if err != nil && !os.IsNotExist(err) {
+					return err
+				}
+				if n == "" {
+					n = d.Type().String()
+				}
+				name += n
+			}
+			names = append(names, name)
+			return nil
+		})
+	return names, err
+}
diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go
index 027acbdabc..35322c7eac 100644
--- a/pkg/util/utils_test.go
+++ b/pkg/util/utils_test.go
@@ -280,7 +280,7 @@ func TestPeriodAndQuotaToCores(t *testing.T) {
 }
 
 func TestParseInputTime(t *testing.T) {
-	tm, err := ParseInputTime("1.5")
+	tm, err := ParseInputTime("1.5", true)
 	if err != nil {
 		t.Errorf("expected error to be nil but was: %v", err)
 	}
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index d03a2741b1..1b75faa40c 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -264,6 +264,11 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
 	if rootless.IsRootless() {
 		storageFs = ROOTLESS_STORAGE_FS
 	}
+	if os.Getenv("STORAGE_FS") != "" {
+		storageFs = os.Getenv("STORAGE_FS")
+		storageOptions = "--storage-driver " + storageFs
+	}
+
 	p := &PodmanTestIntegration{
 		PodmanTest: PodmanTest{
 			PodmanBinary:  podmanBinary,
diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go
index e2a1693839..46ea10c563 100644
--- a/test/e2e/events_test.go
+++ b/test/e2e/events_test.go
@@ -184,6 +184,19 @@ var _ = Describe("Podman events", func() {
 		Expect(result.OutputToString()).To(ContainSubstring(name2))
 		Expect(result.OutputToString()).To(ContainSubstring(name3))
 
+		// string duration in 10 seconds
+		untilT := time.Now().Add(time.Second * 9)
+		result = podmanTest.Podman([]string{"events", "--since", "30s", "--until", "10s"})
+		result.Wait(11)
+		Expect(result).Should(Exit(0))
+		tEnd := time.Now()
+		outDur := tEnd.Sub(untilT)
+		diff := outDur.Seconds() > 0
+		Expect(diff).To(Equal(true))
+		Expect(result.OutputToString()).To(ContainSubstring(name1))
+		Expect(result.OutputToString()).To(ContainSubstring(name2))
+		Expect(result.OutputToString()).To(ContainSubstring(name3))
+
 		wg.Wait()
 	})
 })
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index 0a973b802e..71d30f063f 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -145,7 +145,7 @@ var _ = Describe("Podman logs", func() {
 			results := podmanTest.Podman([]string{"logs", "--until", "10m", cid})
 			results.WaitWithDefaultTimeout()
 			Expect(results).To(Exit(0))
-			Expect(len(results.OutputToStringArray())).To(Equal(0))
+			Expect(len(results.OutputToStringArray())).To(Equal(3))
 		})
 
 		It("until time NOW: "+log, func() {
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index 0286892115..13c8d7ad47 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -117,6 +117,21 @@ var _ = Describe("Podman pod create", func() {
 		Expect(check).Should(Exit(0))
 	})
 
+	It("podman create pod with id file with network portbindings", func() {
+		file := filepath.Join(podmanTest.TempDir, "pod.id")
+		name := "test"
+		session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", "8080:80"})
+		session.WaitWithDefaultTimeout()
+		Expect(session).Should(Exit(0))
+
+		webserver := podmanTest.Podman([]string{"run", "--pod-id-file", file, "-dt", nginx})
+		webserver.WaitWithDefaultTimeout()
+		Expect(webserver).Should(Exit(0))
+
+		check := SystemExec("nc", []string{"-z", "localhost", "8080"})
+		Expect(check).Should(Exit(0))
+	})
+
 	It("podman create pod with no infra but portbindings should fail", func() {
 		name := "test"
 		session := podmanTest.Podman([]string{"pod", "create", "--infra=false", "--name", name, "-p", "80:80"})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 57d57554cc..109a189cda 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -1315,10 +1315,10 @@ USER mail`, BB)
 		}
 
 		curCgroupsBytes, err := ioutil.ReadFile("/proc/self/cgroup")
-		Expect(err).To(BeNil())
-		var curCgroups string = string(curCgroupsBytes)
+		Expect(err).ShouldNot(HaveOccurred())
+		var curCgroups = string(curCgroupsBytes)
 		fmt.Printf("Output:\n%s\n", curCgroups)
-		Expect(curCgroups).To(Not(Equal("")))
+		Expect(curCgroups).ToNot(Equal(""))
 
 		ctrName := "testctr"
 		container := podmanTest.Podman([]string{"run", "--name", ctrName, "-d", "--cgroups=disabled", ALPINE, "top"})
@@ -1329,14 +1329,14 @@ USER mail`, BB)
 		inspectOut := podmanTest.InspectContainer(ctrName)
 		Expect(len(inspectOut)).To(Equal(1))
 		pid := inspectOut[0].State.Pid
-		Expect(pid).To(Not(Equal(0)))
+		Expect(pid).ToNot(Equal(0))
 		Expect(inspectOut[0].HostConfig.CgroupParent).To(Equal(""))
 
 		ctrCgroupsBytes, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
-		Expect(err).To(BeNil())
-		var ctrCgroups string = string(ctrCgroupsBytes)
+		Expect(err).ShouldNot(HaveOccurred())
+		var ctrCgroups = string(ctrCgroupsBytes)
 		fmt.Printf("Output\n:%s\n", ctrCgroups)
-		Expect(curCgroups).To(Equal(ctrCgroups))
+		Expect(ctrCgroups).To(Equal(curCgroups))
 	})
 
 	It("podman run with cgroups=enabled makes cgroups", func() {