aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml2
-rw-r--r--README.md5
-rw-r--r--cmd/podman/system/prune.go17
-rw-r--r--cmd/podman/utils/utils.go35
-rw-r--r--docs/source/_static/api.html2
-rw-r--r--go.mod4
-rw-r--r--go.sum6
-rw-r--r--libpod/container_internal_linux.go27
-rw-r--r--libpod/events/journal_linux.go7
-rw-r--r--libpod/filters/helpers.go20
-rw-r--r--libpod/image/image.go2
-rw-r--r--libpod/image/prune.go23
-rw-r--r--libpod/image/utils.go3
-rw-r--r--libpod/networking_linux.go5
-rw-r--r--libpod/oci_conmon_exec_linux.go2
-rw-r--r--libpod/oci_conmon_linux.go28
-rw-r--r--libpod/runtime_ctr.go27
-rw-r--r--libpod/runtime_pod_infra_linux.go28
-rw-r--r--libpod/runtime_volume.go25
-rw-r--r--libpod/util.go9
-rw-r--r--libpod/volume.go14
-rw-r--r--nix/nixpkgs.json8
-rw-r--r--pkg/api/handlers/compat/containers.go49
-rw-r--r--pkg/api/handlers/compat/containers_prune.go34
-rw-r--r--pkg/api/handlers/compat/images.go10
-rw-r--r--pkg/api/handlers/compat/resize.go8
-rw-r--r--pkg/api/handlers/compat/volumes.go4
-rw-r--r--pkg/api/handlers/libpod/images.go4
-rw-r--r--pkg/api/handlers/libpod/images_pull.go4
-rw-r--r--pkg/api/handlers/libpod/system.go19
-rw-r--r--pkg/api/handlers/libpod/volumes.go12
-rw-r--r--pkg/api/handlers/utils/pods.go4
-rw-r--r--pkg/api/server/swagger.go3
-rw-r--r--pkg/bindings/containers/containers.go5
-rw-r--r--pkg/bindings/images/images.go8
-rw-r--r--pkg/bindings/test/containers_test.go15
-rw-r--r--pkg/bindings/test/images_test.go3
-rw-r--r--pkg/bindings/test/system_test.go35
-rw-r--r--pkg/bindings/test/volumes_test.go3
-rw-r--r--pkg/bindings/volumes/volumes.go5
-rw-r--r--pkg/domain/entities/containers.go7
-rw-r--r--pkg/domain/entities/engine_container.go5
-rw-r--r--pkg/domain/entities/engine_image.go3
-rw-r--r--pkg/domain/entities/images.go5
-rw-r--r--pkg/domain/entities/reports/prune.go40
-rw-r--r--pkg/domain/entities/system.go10
-rw-r--r--pkg/domain/entities/volumes.go5
-rw-r--r--pkg/domain/filters/containers.go (renamed from libpod/filters/containers.go)3
-rw-r--r--pkg/domain/filters/pods.go (renamed from libpod/filters/pods.go)2
-rw-r--r--pkg/domain/infra/abi/containers.go21
-rw-r--r--pkg/domain/infra/abi/images.go14
-rw-r--r--pkg/domain/infra/abi/play.go14
-rw-r--r--pkg/domain/infra/abi/pods.go4
-rw-r--r--pkg/domain/infra/abi/system.go36
-rw-r--r--pkg/domain/infra/abi/volumes.go14
-rw-r--r--pkg/domain/infra/tunnel/containers.go3
-rw-r--r--pkg/domain/infra/tunnel/images.go15
-rw-r--r--pkg/domain/infra/tunnel/volumes.go3
-rw-r--r--pkg/ps/ps.go6
-rw-r--r--pkg/specgen/generate/kube/kube.go83
-rw-r--r--pkg/specgen/generate/namespaces.go4
-rw-r--r--pkg/specgen/generate/security.go12
-rw-r--r--pkg/systemd/generate/common.go5
-rw-r--r--pkg/systemd/generate/containers.go6
-rw-r--r--pkg/systemd/generate/containers_test.go43
-rw-r--r--pkg/systemd/generate/pods.go6
-rw-r--r--pkg/systemd/generate/pods_test.go15
-rw-r--r--test/apiv2/20-containers.at9
-rw-r--r--test/apiv2/45-system.at6
-rw-r--r--test/e2e/exec_test.go15
-rw-r--r--test/e2e/generate_systemd_test.go3
-rw-r--r--test/e2e/pod_stats_test.go3
-rw-r--r--test/e2e/run_privileged_test.go45
-rw-r--r--test/e2e/run_test.go8
-rw-r--r--test/e2e/systemd_test.go27
-rw-r--r--vendor/github.com/containers/psgo/internal/capabilities/capabilities.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/dev/tty.go5
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/status.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/process/process.go4
-rw-r--r--vendor/github.com/containers/psgo/psgo.go24
-rw-r--r--vendor/github.com/google/uuid/uuid.go10
-rw-r--r--vendor/modules.txt4
82 files changed, 645 insertions, 430 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index cbe8bc757..18cb889ad 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -30,7 +30,7 @@ env:
PRIOR_UBUNTU_NAME: "ubuntu-2004"
# Google-cloud VM Images
- IMAGE_SUFFIX: "c6233039174893568"
+ IMAGE_SUFFIX: "c6524344056676352"
FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}"
UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX}"
diff --git a/README.md b/README.md
index e09334d35..89dd012c7 100644
--- a/README.md
+++ b/README.md
@@ -177,9 +177,8 @@ familiar container cli commands. For more details, see the
[Container Tools Guide](https://github.com/containers/buildah/tree/master/docs/containertools).
## Podman Former API (Varlink)
-Podman formerly offered a [Varlink-based API](https://github.com/containers/podman/blob/master/docs/tutorials/varlink_remote_client.md)
-for remote management of containers. However, this API was replaced by the REST API.
-Varlink support has been removed as of the 3.0 release.
+Podman formerly offered a Varlink-based API for remote management of containers. However, this API
+was replaced by the REST API. Varlink support has been removed as of the 3.0 release.
For more details, you can see [this blog](https://podman.io/blogs/2020/01/17/podman-new-api.html).
## Static Binary Builds
diff --git a/cmd/podman/system/prune.go b/cmd/podman/system/prune.go
index a74363684..87bb947ed 100644
--- a/cmd/podman/system/prune.go
+++ b/cmd/podman/system/prune.go
@@ -11,8 +11,9 @@ import (
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/utils"
"github.com/containers/podman/v2/cmd/podman/validate"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/pkg/domain/entities"
+ dfilters "github.com/containers/podman/v2/pkg/domain/filters"
+ "github.com/docker/go-units"
"github.com/spf13/cobra"
)
@@ -80,7 +81,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
}
}
- pruneOptions.Filters, err = lpfilters.ParseFilterArgumentsIntoFilters(filters)
+ pruneOptions.Filters, err = dfilters.ParseFilterArgumentsIntoFilters(filters)
if err != nil {
return err
}
@@ -90,7 +91,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
return err
}
// Print container prune results
- err = utils.PrintContainerPruneResults(response.ContainerPruneReport, true)
+ err = utils.PrintContainerPruneResults(response.ContainerPruneReports, true)
if err != nil {
return err
}
@@ -101,11 +102,17 @@ Are you sure you want to continue? [y/N] `, volumeString)
}
// Print Volume prune results
if pruneOptions.Volume {
- err = utils.PrintVolumePruneResults(response.VolumePruneReport, true)
+ err = utils.PrintVolumePruneResults(response.VolumePruneReports, true)
if err != nil {
return err
}
}
// Print Images prune results
- return utils.PrintImagePruneResults(response.ImagePruneReport, true)
+ err = utils.PrintImagePruneResults(response.ImagePruneReports, true)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("Total reclaimed space: %s\n", units.HumanSize((float64)(response.ReclaimedSpace)))
+ return nil
}
diff --git a/cmd/podman/utils/utils.go b/cmd/podman/utils/utils.go
index 2ca2c4c92..f42243f69 100644
--- a/cmd/podman/utils/utils.go
+++ b/cmd/podman/utils/utils.go
@@ -5,6 +5,7 @@ import (
"os"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
)
// IsDir returns true if the specified path refers to a directory.
@@ -41,21 +42,21 @@ func PrintPodPruneResults(podPruneReports []*entities.PodPruneReport, heading bo
return errs.PrintErrors()
}
-func PrintContainerPruneResults(containerPruneReport *entities.ContainerPruneReport, heading bool) error {
+func PrintContainerPruneResults(containerPruneReports []*reports.PruneReport, heading bool) error {
var errs OutputErrors
- if heading && (len(containerPruneReport.ID) > 0 || len(containerPruneReport.Err) > 0) {
+ if heading && (len(containerPruneReports) > 0) {
fmt.Println("Deleted Containers")
}
- for k := range containerPruneReport.ID {
- fmt.Println(k)
- }
- for _, v := range containerPruneReport.Err {
- errs = append(errs, v)
+ for _, v := range containerPruneReports {
+ fmt.Println(v.Id)
+ if v.Err != nil {
+ errs = append(errs, v.Err)
+ }
}
return errs.PrintErrors()
}
-func PrintVolumePruneResults(volumePruneReport []*entities.VolumePruneReport, heading bool) error {
+func PrintVolumePruneResults(volumePruneReport []*reports.PruneReport, heading bool) error {
var errs OutputErrors
if heading && len(volumePruneReport) > 0 {
fmt.Println("Deleted Volumes")
@@ -70,18 +71,16 @@ func PrintVolumePruneResults(volumePruneReport []*entities.VolumePruneReport, he
return errs.PrintErrors()
}
-func PrintImagePruneResults(imagePruneReport *entities.ImagePruneReport, heading bool) error {
- if heading && (len(imagePruneReport.Report.Id) > 0 || len(imagePruneReport.Report.Err) > 0) {
+func PrintImagePruneResults(imagePruneReports []*reports.PruneReport, heading bool) error {
+ if heading {
fmt.Println("Deleted Images")
}
- for _, i := range imagePruneReport.Report.Id {
- fmt.Println(i)
- }
- for _, e := range imagePruneReport.Report.Err {
- fmt.Fprint(os.Stderr, e.Error()+"\n")
- }
- if imagePruneReport.Size > 0 {
- fmt.Fprintf(os.Stdout, "Size: %d\n", imagePruneReport.Size)
+ for _, r := range imagePruneReports {
+ fmt.Println(r.Id)
+ if r.Err != nil {
+ fmt.Fprint(os.Stderr, r.Err.Error()+"\n")
+ }
}
+
return nil
}
diff --git a/docs/source/_static/api.html b/docs/source/_static/api.html
index 8b9d66e0d..11fbb85a0 100644
--- a/docs/source/_static/api.html
+++ b/docs/source/_static/api.html
@@ -18,7 +18,7 @@
</style>
</head>
<body>
- <redoc spec-url='https://storage.googleapis.com/libpod-master-releases/swagger-latest-master.yaml'></redoc>
+ <redoc spec-url='https://storage.googleapis.com/libpod-master-releases/swagger-latest-master.yaml' sort-props-alphabetically></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
</body>
</html>
diff --git a/go.mod b/go.mod
index 8312ae852..0398c5bad 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
github.com/containers/common v0.31.2
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.9.0
- github.com/containers/psgo v1.5.1
+ github.com/containers/psgo v1.5.2
github.com/containers/storage v1.24.4
github.com/coreos/go-systemd/v22 v22.1.0
github.com/cri-o/ocicni v0.2.1-0.20201125151022-df072ea5421c
@@ -29,7 +29,7 @@ require (
github.com/ghodss/yaml v1.0.0
github.com/godbus/dbus/v5 v5.0.3
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
- github.com/google/uuid v1.1.2
+ github.com/google/uuid v1.1.3
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
github.com/hashicorp/go-multierror v1.1.0
diff --git a/go.sum b/go.sum
index 1daf52402..b5a64b01e 100644
--- a/go.sum
+++ b/go.sum
@@ -114,8 +114,8 @@ github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDpl
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6GzVe1c=
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
-github.com/containers/psgo v1.5.1 h1:MQNb7FLbXqBdqz6u4lI2QWizVz4RSTzs1+Nk9XT1iVA=
-github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
+github.com/containers/psgo v1.5.2 h1:3aoozst/GIwsrr/5jnFy3FrJay98uujPCu9lTuSZ/Cw=
+github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
github.com/containers/storage v1.23.7/go.mod h1:cUT2zHjtx+WlVri30obWmM2gpqpi8jfPsmIzP1TVpEI=
github.com/containers/storage v1.24.1/go.mod h1:0xJL06Dmd+ZYXIUdnBUPN0JnhHGgwMkLvnnAonJfWJU=
github.com/containers/storage v1.24.3 h1:8UB4S62l4hrU6Yw3dbsLCJtLg7Ofo39IN2HdckBIX4E=
@@ -266,6 +266,8 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.3 h1:twObb+9XcuH5B9V1TBCvvvZoO6iEdILi2a76PYn5rJI=
+github.com/google/uuid v1.1.3/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 05b149e03..cefe12209 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -529,14 +529,37 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
+ // Hostname handling:
+ // If we have a UTS namespace, set Hostname in the OCI spec.
+ // Set the HOSTNAME environment variable unless explicitly overridden by
+ // the user (already present in OCI spec). If we don't have a UTS ns,
+ // set it to the host's hostname instead.
+ hostname := c.Hostname()
+ foundUTS := false
for _, i := range c.config.Spec.Linux.Namespaces {
if i.Type == spec.UTSNamespace && i.Path == "" {
- hostname := c.Hostname()
+ foundUTS = true
g.SetHostname(hostname)
- g.AddProcessEnv("HOSTNAME", hostname)
break
}
}
+ if !foundUTS {
+ tmpHostname, err := os.Hostname()
+ if err != nil {
+ return nil, err
+ }
+ hostname = tmpHostname
+ }
+ needEnv := true
+ for _, checkEnv := range g.Config.Process.Env {
+ if strings.SplitN(checkEnv, "=", 2)[0] == "HOSTNAME" {
+ needEnv = false
+ break
+ }
+ }
+ if needEnv {
+ g.AddProcessEnv("HOSTNAME", hostname)
+ }
if c.config.UTSNsCtr != "" {
if err := c.addNamespaceContainer(&g, UTSNS, c.config.UTSNsCtr, spec.UTSNamespace); err != nil {
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 71c638017..8b7e448b1 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -84,7 +84,11 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return err
}
-
+ defer func() {
+ if err := j.Close(); err != nil {
+ logrus.Errorf("Unable to close journal :%v", err)
+ }
+ }()
// match only podman journal entries
podmanJournal := sdjournal.Match{Field: "SYSLOG_IDENTIFIER", Value: "podman"}
if err := j.AddMatch(podmanJournal.String()); err != nil {
@@ -112,7 +116,6 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return errors.Wrap(err, "failed to get journal cursor")
}
-
for {
select {
case <-ctx.Done():
diff --git a/libpod/filters/helpers.go b/libpod/filters/helpers.go
deleted file mode 100644
index 859db3a9a..000000000
--- a/libpod/filters/helpers.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package lpfilters
-
-import (
- "net/url"
- "strings"
-
- "github.com/pkg/errors"
-)
-
-func ParseFilterArgumentsIntoFilters(filters []string) (url.Values, error) {
- parsedFilters := make(url.Values)
- for _, f := range filters {
- t := strings.SplitN(f, "=", 2)
- if len(t) < 2 {
- return parsedFilters, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
- }
- parsedFilters.Add(t[0], t[1])
- }
- return parsedFilters, nil
-}
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 5c3f3b9e4..a9082b2c6 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -497,7 +497,7 @@ func (ir *Runtime) getLocalImage(inputName string) (string, *storage.Image, erro
return inputName, repoImage, nil
}
- return "", nil, errors.Wrapf(ErrNoSuchImage, err.Error())
+ return "", nil, err
}
// ID returns the image ID as a string
diff --git a/libpod/image/prune.go b/libpod/image/prune.go
index b38265a7e..3c06a89c2 100644
--- a/libpod/image/prune.go
+++ b/libpod/image/prune.go
@@ -6,6 +6,7 @@ import (
"time"
"github.com/containers/podman/v2/libpod/events"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/timetype"
"github.com/containers/storage"
"github.com/pkg/errors"
@@ -110,7 +111,8 @@ func (ir *Runtime) GetPruneImages(ctx context.Context, all bool, filterFuncs []I
// PruneImages prunes dangling and optionally all unused images from the local
// image store
-func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ([]string, error) {
+func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ([]*reports.PruneReport, error) {
+ preports := make([]*reports.PruneReport, 0)
filterFuncs := make([]ImageFilter, 0, len(filter))
for _, f := range filter {
filterSplit := strings.SplitN(f, "=", 2)
@@ -125,7 +127,6 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
filterFuncs = append(filterFuncs, generatedFunc)
}
- pruned := []string{}
prev := 0
for {
toPrune, err := ir.GetPruneImages(ctx, all, filterFuncs)
@@ -143,6 +144,13 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
if err != nil {
return nil, err
}
+ nameOrID := img.ID()
+ s, err := img.Size(ctx)
+ imgSize := *s
+ if err != nil {
+ logrus.Warnf("Failed to collect image size for: %s, %s", nameOrID, err)
+ imgSize = 0
+ }
if err := img.Remove(ctx, false); err != nil {
if errors.Cause(err) == storage.ErrImageUsedByContainer {
logrus.Warnf("Failed to prune image %s as it is in use: %v.\nA container associated with containers/storage (e.g., Buildah, CRI-O, etc.) maybe associated with this image.\nUsing the rmi command with the --force option will remove the container and image, but may cause failures for other dependent systems.", img.ID(), err)
@@ -151,13 +159,18 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
return nil, errors.Wrap(err, "failed to prune image")
}
defer img.newImageEvent(events.Prune)
- nameOrID := img.ID()
+
if len(repotags) > 0 {
nameOrID = repotags[0]
}
- pruned = append(pruned, nameOrID)
+
+ preports = append(preports, &reports.PruneReport{
+ Id: nameOrID,
+ Err: nil,
+ Size: uint64(imgSize),
+ })
}
}
- return pruned, nil
+ return preports, nil
}
diff --git a/libpod/image/utils.go b/libpod/image/utils.go
index 727c73a71..5e7fed5c6 100644
--- a/libpod/image/utils.go
+++ b/libpod/image/utils.go
@@ -45,7 +45,8 @@ func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, er
}
}
if len(candidates) == 0 {
- return nil, errors.Errorf("unable to find a name and tag match for %s in repotags", searchName)
+
+ return nil, errors.Wrapf(define.ErrNoSuchImage, "unable to find a name and tag match for %s in repotags", searchName)
}
// If more then one candidate and the candidates all have same name
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 863e82efd..be6867399 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -247,6 +247,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
func (r *Runtime) setupSlirp4netns(ctr *Container) error {
path := r.config.Engine.NetworkCmdPath
slirpOptions := r.config.Engine.NetworkCmdOptions
+ noPivotRoot := r.config.Engine.NoPivotRoot
if path == "" {
var err error
path, err = exec.LookPath("slirp4netns")
@@ -351,7 +352,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
if slirpFeatures.HasMTU {
cmdArgs = append(cmdArgs, "--mtu", "65520")
}
- if slirpFeatures.HasEnableSandbox {
+ if !noPivotRoot && slirpFeatures.HasEnableSandbox {
cmdArgs = append(cmdArgs, "--enable-sandbox")
}
if slirpFeatures.HasEnableSeccomp {
@@ -424,7 +425,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
}
// workaround for https://github.com/rootless-containers/slirp4netns/pull/153
- if slirpFeatures.HasEnableSandbox {
+ if !noPivotRoot && slirpFeatures.HasEnableSandbox {
cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWNS
cmd.SysProcAttr.Unshareflags = syscall.CLONE_NEWNS
}
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index f8e7020f7..4546acefb 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -387,7 +387,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
finalEnv = append(finalEnv, fmt.Sprintf("%s=%s", k, v))
}
- processFile, err := prepareProcessExec(c, options.Cmd, finalEnv, options.Terminal, options.Cwd, options.User, sessionID)
+ processFile, err := prepareProcessExec(c, options, finalEnv, sessionID)
if err != nil {
return nil, nil, err
}
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index c99086b33..e7cb5a802 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -193,6 +193,11 @@ func hasCurrentUserMapped(ctr *Container) bool {
// CreateContainer creates a container.
func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) error {
+ // always make the run dir accessible to the current user so that the PID files can be read without
+ // being in the rootless user namespace.
+ if err := makeAccessible(ctr.state.RunDir, 0, 0); err != nil {
+ return err
+ }
if !hasCurrentUserMapped(ctr) {
for _, i := range []string{ctr.state.RunDir, ctr.runtime.config.Engine.TmpDir, ctr.config.StaticDir, ctr.state.Mountpoint, ctr.runtime.config.Engine.VolumePath} {
if err := makeAccessible(i, ctr.RootUID(), ctr.RootGID()); err != nil {
@@ -1185,26 +1190,36 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
// prepareProcessExec returns the path of the process.json used in runc exec -p
// caller is responsible to close the returned *os.File if needed.
-func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, sessionID string) (*os.File, error) {
+func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessionID string) (*os.File, error) {
f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
if err != nil {
return nil, err
}
- pspec := c.config.Spec.Process
+ pspec := new(spec.Process)
+ if err := JSONDeepCopy(c.config.Spec.Process, pspec); err != nil {
+ return nil, err
+ }
pspec.SelinuxLabel = c.config.ProcessLabel
- pspec.Args = cmd
+ pspec.Args = options.Cmd
+ for _, cap := range options.CapAdd {
+ pspec.Capabilities.Bounding = append(pspec.Capabilities.Bounding, cap)
+ pspec.Capabilities.Effective = append(pspec.Capabilities.Effective, cap)
+ pspec.Capabilities.Inheritable = append(pspec.Capabilities.Inheritable, cap)
+ pspec.Capabilities.Permitted = append(pspec.Capabilities.Permitted, cap)
+ pspec.Capabilities.Ambient = append(pspec.Capabilities.Ambient, cap)
+ }
// We need to default this to false else it will inherit terminal as true
// from the container.
pspec.Terminal = false
- if tty {
+ if options.Terminal {
pspec.Terminal = true
}
if len(env) > 0 {
pspec.Env = append(pspec.Env, env...)
}
- if cwd != "" {
- pspec.Cwd = cwd
+ if options.Cwd != "" {
+ pspec.Cwd = options.Cwd
}
@@ -1212,6 +1227,7 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
var sgids []uint32
// if the user is empty, we should inherit the user that the container is currently running with
+ user := options.User
if user == "" {
user = c.config.User
addGroups = c.config.Groups
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 14b537ca2..f22e48746 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/podman/v2/libpod/shutdown"
"github.com/containers/podman/v2/pkg/cgroups"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/storage"
"github.com/containers/storage/pkg/stringid"
@@ -884,9 +885,8 @@ func (r *Runtime) GetExecSessionContainer(id string) (*Container, error) {
// PruneContainers removes stopped and exited containers from localstorage. A set of optional filters
// can be provided to be more granular.
-func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int64, map[string]error, error) {
- pruneErrors := make(map[string]error)
- prunedContainers := make(map[string]int64)
+func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) ([]*reports.PruneReport, error) {
+ preports := make([]*reports.PruneReport, 0)
// We add getting the exited and stopped containers via a filter
containerStateFilter := func(c *Container) bool {
if c.PodID() != "" {
@@ -906,23 +906,28 @@ func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int
filterFuncs = append(filterFuncs, containerStateFilter)
delContainers, err := r.GetContainers(filterFuncs...)
if err != nil {
- return nil, nil, err
+ return nil, err
}
for _, c := range delContainers {
- ctr := c
- size, err := ctr.RWSize()
+ report := new(reports.PruneReport)
+ report.Id = c.ID()
+ report.Err = nil
+ report.Size = 0
+ size, err := c.RWSize()
if err != nil {
- pruneErrors[ctr.ID()] = err
+ report.Err = err
+ preports = append(preports, report)
continue
}
- err = r.RemoveContainer(context.Background(), ctr, false, false)
+ err = r.RemoveContainer(context.Background(), c, false, false)
if err != nil {
- pruneErrors[ctr.ID()] = err
+ report.Err = err
} else {
- prunedContainers[ctr.ID()] = size
+ report.Size = (uint64)(size)
}
+ preports = append(preports, report)
}
- return prunedContainers, pruneErrors, nil
+ return preports, nil
}
// MountStorageContainer mounts the storage container's root filesystem
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 3e4185db1..dd957527d 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -159,6 +159,34 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
g.AddMount(devPts)
}
+ // Add default sysctls from containers.conf
+ defaultSysctls, err := util.ValidateSysctls(r.config.Sysctls())
+ if err != nil {
+ return nil, err
+ }
+ for sysctlKey, sysctlVal := range defaultSysctls {
+ // Ignore mqueue sysctls if not sharing IPC
+ if !p.config.UsePodIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
+ logrus.Infof("Sysctl %s=%s ignored in containers.conf, since IPC Namespace for pod is unused", sysctlKey, sysctlVal)
+
+ continue
+ }
+
+ // Ignore net sysctls if host network or not sharing network
+ if (p.config.InfraContainer.HostNetwork || !p.config.UsePodNet) && strings.HasPrefix(sysctlKey, "net.") {
+ logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace for pod is unused", sysctlKey, sysctlVal)
+ continue
+ }
+
+ // Ignore uts sysctls if not sharing UTS
+ if !p.config.UsePodUTS && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) {
+ logrus.Infof("Sysctl %s=%s ignored in containers.conf, since UTS Namespace for pod is unused", sysctlKey, sysctlVal)
+ continue
+ }
+
+ g.AddLinuxSysctl(sysctlKey, sysctlVal)
+ }
+
containerName := p.ID()[:IDTruncLength] + "-infra"
options = append(options, r.WithPod(p))
options = append(options, WithRootFSFromImage(imgID, imgName, rawImageName))
diff --git a/libpod/runtime_volume.go b/libpod/runtime_volume.go
index 10c32a119..9d985f905 100644
--- a/libpod/runtime_volume.go
+++ b/libpod/runtime_volume.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/pkg/errors"
)
@@ -133,22 +134,32 @@ func (r *Runtime) GetAllVolumes() ([]*Volume, error) {
}
// PruneVolumes removes unused volumes from the system
-func (r *Runtime) PruneVolumes(ctx context.Context, filterFuncs []VolumeFilter) (map[string]error, error) {
- reports := make(map[string]error)
+func (r *Runtime) PruneVolumes(ctx context.Context, filterFuncs []VolumeFilter) ([]*reports.PruneReport, error) {
+ preports := make([]*reports.PruneReport, 0)
vols, err := r.Volumes(filterFuncs...)
if err != nil {
return nil, err
}
for _, vol := range vols {
+ report := new(reports.PruneReport)
+ volSize, err := vol.Size()
+ if err != nil {
+ volSize = 0
+ }
+ report.Size = volSize
+ report.Id = vol.Name()
if err := r.RemoveVolume(ctx, vol, false); err != nil {
if errors.Cause(err) != define.ErrVolumeBeingUsed && errors.Cause(err) != define.ErrVolumeRemoved {
- reports[vol.Name()] = err
+ report.Err = err
+ } else {
+ // We didn't remove the volume for some reason
+ continue
}
- continue
+ } else {
+ vol.newVolumeEvent(events.Prune)
}
- vol.newVolumeEvent(events.Prune)
- reports[vol.Name()] = nil
+ preports = append(preports, report)
}
- return reports, nil
+ return preports, nil
}
diff --git a/libpod/util.go b/libpod/util.go
index 8faf665e7..bf9bf2542 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -153,6 +153,10 @@ func queryPackageVersion(cmdArg ...string) string {
return strings.Trim(output, "\n")
}
+func equeryVersion(path string) string {
+ return queryPackageVersion("/usr/bin/equery", "b", path)
+}
+
func pacmanVersion(path string) string {
return queryPackageVersion("/usr/bin/pacman", "-Qo", path)
}
@@ -172,7 +176,10 @@ func packageVersion(program string) string {
if out := dpkgVersion(program); out != unknownPackage {
return out
}
- return pacmanVersion(program)
+ if out := pacmanVersion(program); out != unknownPackage {
+ return out
+ }
+ return equeryVersion(program)
}
func programVersion(mountProgram string) (string, error) {
diff --git a/libpod/volume.go b/libpod/volume.go
index 0535bf4db..ed08d375f 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -1,6 +1,8 @@
package libpod
import (
+ "os"
+ "path/filepath"
"time"
"github.com/containers/podman/v2/libpod/define"
@@ -79,6 +81,18 @@ func (v *Volume) Name() string {
return v.config.Name
}
+// Returns the size on disk of volume
+func (v *Volume) Size() (uint64, error) {
+ var size uint64
+ err := filepath.Walk(v.config.MountPoint, func(path string, info os.FileInfo, err error) error {
+ if err == nil && !info.IsDir() {
+ size += (uint64)(info.Size())
+ }
+ return err
+ })
+ return size, err
+}
+
// Driver retrieves the volume's driver.
func (v *Volume) Driver() string {
return v.config.Driver
diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json
index 8e001f6b2..d304de536 100644
--- a/nix/nixpkgs.json
+++ b/nix/nixpkgs.json
@@ -1,9 +1,9 @@
{
"url": "https://github.com/nixos/nixpkgs",
- "rev": "6ea2fd15d881006b41ea5bbed0f76bffcd85f9f9",
- "date": "2020-12-20T13:26:58+10:00",
- "path": "/nix/store/kyw1ackbp9qh1jzlzwmjvi5i3541ym5z-nixpkgs",
- "sha256": "0kgqmw4ki10b37530jh912sn49x3gay5cnmfr8yz2yp8nvkrk236",
+ "rev": "4a75203f0270f96cbc87f5dfa5d5185690237d87",
+ "date": "2020-12-29T03:18:48+01:00",
+ "path": "/nix/store/scswsm6r4jnhp9ki0f6s81kpj5x6jkn7-nixpkgs",
+ "sha256": "0h70fm9aa7s06wkalbadw70z5rscbs3p6nblb47z523nhlzgjxk9",
"fetchSubmodules": false,
"deepClone": false,
"leaveDotGit": false
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 7a3e5dd84..0f89c859e 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net/http"
+ "sort"
"strconv"
"strings"
"syscall"
@@ -13,6 +14,8 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/domain/filters"
+ "github.com/containers/podman/v2/pkg/ps"
"github.com/containers/podman/v2/pkg/signal"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
@@ -78,10 +81,6 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
}
func ListContainers(w http.ResponseWriter, r *http.Request) {
- var (
- containers []*libpod.Container
- err error
- )
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
@@ -97,22 +96,48 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
- if query.All {
- containers, err = runtime.GetAllContainers()
- } else {
- containers, err = runtime.GetRunningContainers()
+
+ filterFuncs := make([]libpod.ContainerFilter, 0, len(query.Filters))
+ all := query.All || query.Limit > 0
+ if len(query.Filters) > 0 {
+ for k, v := range query.Filters {
+ generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filterFuncs = append(filterFuncs, generatedFunc)
+ }
}
+
+ // Docker thinks that if status is given as an input, then we should override
+ // the all setting and always deal with all containers.
+ if len(query.Filters["status"]) > 0 {
+ all = true
+ }
+ if !all {
+ runningOnly, err := filters.GenerateContainerFilterFuncs("status", []string{define.ContainerStateRunning.String()}, runtime)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filterFuncs = append(filterFuncs, runningOnly)
+ }
+
+ containers, err := runtime.GetContainers(filterFuncs...)
if err != nil {
utils.InternalServerError(w, err)
return
}
if _, found := r.URL.Query()["limit"]; found && query.Limit > 0 {
- last := query.Limit
- if len(containers) > last {
- containers = containers[len(containers)-last:]
+ // Sort the libpod containers
+ sort.Sort(ps.SortCreateTime{SortContainers: containers})
+ // we should perform the lopping before we start getting
+ // the expensive information on containers
+ if len(containers) > query.Limit {
+ containers = containers[:query.Limit]
}
}
- // TODO filters still need to be applied
var list = make([]*handlers.Container, len(containers))
for i, ctnr := range containers {
api, err := LibpodToContainer(ctnr, query.Size)
diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go
index 2cfeebcce..b3d26b8f4 100644
--- a/pkg/api/handlers/compat/containers_prune.go
+++ b/pkg/api/handlers/compat/containers_prune.go
@@ -4,19 +4,14 @@ import (
"net/http"
"github.com/containers/podman/v2/libpod"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
- "github.com/containers/podman/v2/pkg/domain/entities"
- "github.com/docker/docker/api/types"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
+ "github.com/containers/podman/v2/pkg/domain/filters"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
func PruneContainers(w http.ResponseWriter, r *http.Request) {
- var (
- delContainers []string
- space int64
- )
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
@@ -29,7 +24,7 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) {
}
filterFuncs := make([]libpod.ContainerFilter, 0, len(query.Filters))
for k, v := range query.Filters {
- generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, v, runtime)
+ generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -49,36 +44,21 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) {
return
}
- prunedContainers, pruneErrors, err := runtime.PruneContainers(filterFuncs)
+ report, err := runtime.PruneContainers(filterFuncs)
if err != nil {
utils.InternalServerError(w, err)
return
}
- for ctrID, size := range prunedContainers {
- if pruneErrors[ctrID] == nil {
- space += size
- delContainers = append(delContainers, ctrID)
- }
- }
- report := types.ContainersPruneReport{
- ContainersDeleted: delContainers,
- SpaceReclaimed: uint64(space),
- }
utils.WriteResponse(w, http.StatusOK, report)
}
func PruneContainersHelper(w http.ResponseWriter, r *http.Request, filterFuncs []libpod.ContainerFilter) (
- *entities.ContainerPruneReport, error) {
+ []*reports.PruneReport, error) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- prunedContainers, pruneErrors, err := runtime.PruneContainers(filterFuncs)
+ reports, err := runtime.PruneContainers(filterFuncs)
if err != nil {
utils.InternalServerError(w, err)
return nil, err
}
-
- report := &entities.ContainerPruneReport{
- Err: pruneErrors,
- ID: prunedContainers,
- }
- return report, nil
+ return reports, nil
}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index dc72500e4..9d7503aba 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -99,21 +99,23 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
filters = append(filters, fmt.Sprintf("%s=%s", k, val))
}
}
- pruneCids, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters)
+ imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters)
if err != nil {
utils.InternalServerError(w, err)
return
}
- for _, p := range pruneCids {
+ reclaimedSpace := uint64(0)
+ for _, p := range imagePruneReports {
idr = append(idr, types.ImageDeleteResponseItem{
- Deleted: p,
+ Deleted: p.Id,
})
+ reclaimedSpace = reclaimedSpace + p.Size
}
// FIXME/TODO to do this exactly correct, pruneimages needs to return idrs and space-reclaimed, then we are golden
ipr := types.ImagesPruneReport{
ImagesDeleted: idr,
- SpaceReclaimed: 1, // TODO we cannot supply this right now
+ SpaceReclaimed: reclaimedSpace,
}
utils.WriteResponse(w, http.StatusOK, handlers.ImagesPruneReport{ImagesPruneReport: ipr})
}
diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go
index bdc051d73..cc8c6ef0a 100644
--- a/pkg/api/handlers/compat/resize.go
+++ b/pkg/api/handlers/compat/resize.go
@@ -20,8 +20,8 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
// /containers/{id}/resize
query := struct {
- height uint16 `schema:"h"`
- width uint16 `schema:"w"`
+ Height uint16 `schema:"h"`
+ Width uint16 `schema:"w"`
}{
// override any golang type defaults
}
@@ -33,8 +33,8 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
}
sz := remotecommand.TerminalSize{
- Width: query.width,
- Height: query.height,
+ Width: query.Width,
+ Height: query.Height,
}
var status int
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index f49f06b17..1188d8f84 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -269,9 +269,9 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
return
}
prunedIds := make([]string, 0, len(pruned))
- for k := range pruned {
+ for _, v := range pruned {
// XXX: This drops any pruning per-volume error messages on the floor
- prunedIds = append(prunedIds, k)
+ prunedIds = append(prunedIds, v.Id)
}
pruneResponse := docker_api_types.VolumesPruneReport{
VolumesDeleted: prunedIds,
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index 0b8712f16..979a8adc4 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -156,12 +156,12 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
}
}
- cids, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, libpodFilters)
+ imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, libpodFilters)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
return
}
- utils.WriteResponse(w, http.StatusOK, cids)
+ utils.WriteResponse(w, http.StatusOK, imagePruneReports)
}
func ExportImage(w http.ResponseWriter, r *http.Request) {
diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go
index 5e2727e95..bacba006d 100644
--- a/pkg/api/handlers/libpod/images_pull.go
+++ b/pkg/api/handlers/libpod/images_pull.go
@@ -115,10 +115,10 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
}
}
- writer := channel.NewWriter(make(chan []byte, 1))
+ writer := channel.NewWriter(make(chan []byte))
defer writer.Close()
- stderr := channel.NewWriter(make(chan []byte, 1))
+ stderr := channel.NewWriter(make(chan []byte))
defer stderr.Close()
images := make([]string, 0, len(imagesToPull))
diff --git a/pkg/api/handlers/libpod/system.go b/pkg/api/handlers/libpod/system.go
index b157dfc7b..130e563ae 100644
--- a/pkg/api/handlers/libpod/system.go
+++ b/pkg/api/handlers/libpod/system.go
@@ -38,35 +38,28 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) {
systemPruneReport.PodPruneReport = podPruneReport
// We could parallelize this, should we?
- containerPruneReport, err := compat.PruneContainersHelper(w, r, nil)
+ containerPruneReports, err := compat.PruneContainersHelper(w, r, nil)
if err != nil {
utils.InternalServerError(w, err)
return
}
- systemPruneReport.ContainerPruneReport = containerPruneReport
+ systemPruneReport.ContainerPruneReports = containerPruneReports
- results, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, nil)
+ imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, nil)
if err != nil {
utils.InternalServerError(w, err)
return
}
- report := entities.ImagePruneReport{
- Report: entities.Report{
- Id: results,
- Err: nil,
- },
- }
-
- systemPruneReport.ImagePruneReport = &report
+ systemPruneReport.ImagePruneReports = imagePruneReports
if query.Volumes {
- volumePruneReport, err := pruneVolumesHelper(r)
+ volumePruneReports, err := pruneVolumesHelper(r)
if err != nil {
utils.InternalServerError(w, err)
return
}
- systemPruneReport.VolumePruneReport = volumePruneReport
+ systemPruneReport.VolumePruneReports = volumePruneReports
}
utils.WriteResponse(w, http.StatusOK, systemPruneReport)
}
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index b02a6a8ce..6f9537515 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/domain/infra/abi/parse"
"github.com/gorilla/schema"
@@ -178,7 +179,7 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, reports)
}
-func pruneVolumesHelper(r *http.Request) ([]*entities.VolumePruneReport, error) {
+func pruneVolumesHelper(r *http.Request) ([]*reports.PruneReport, error) {
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
decoder = r.Context().Value("decoder").(*schema.Decoder)
@@ -199,17 +200,10 @@ func pruneVolumesHelper(r *http.Request) ([]*entities.VolumePruneReport, error)
return nil, err
}
- pruned, err := runtime.PruneVolumes(r.Context(), filterFuncs)
+ reports, err := runtime.PruneVolumes(r.Context(), filterFuncs)
if err != nil {
return nil, err
}
- reports := make([]*entities.VolumePruneReport, 0, len(pruned))
- for k, v := range pruned {
- reports = append(reports, &entities.VolumePruneReport{
- Err: v,
- Id: k,
- })
- }
return reports, nil
}
func RemoveVolume(w http.ResponseWriter, r *http.Request) {
diff --git a/pkg/api/handlers/utils/pods.go b/pkg/api/handlers/utils/pods.go
index 7506dbfd1..0fe3a308b 100644
--- a/pkg/api/handlers/utils/pods.go
+++ b/pkg/api/handlers/utils/pods.go
@@ -4,8 +4,8 @@ import (
"net/http"
"github.com/containers/podman/v2/libpod"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/pkg/domain/entities"
+ dfilters "github.com/containers/podman/v2/pkg/domain/filters"
"github.com/gorilla/schema"
)
@@ -31,7 +31,7 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
filters := make([]libpod.PodFilter, 0, len(query.Filters))
for k, v := range query.Filters {
- f, err := lpfilters.GeneratePodFilterFunc(k, v)
+ f, err := dfilters.GeneratePodFilterFunc(k, v)
if err != nil {
return nil, err
}
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 6d349bb7d..45253e01a 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -4,6 +4,7 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
)
// No such image
@@ -170,7 +171,7 @@ type ok struct {
// swagger:response VolumePruneResponse
type swagVolumePruneResponse struct {
// in:body
- Body []entities.VolumePruneReport
+ Body []reports.PruneReport
}
// Volume create response
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index 650aa9ac5..1081a0e61 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/bindings"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -49,11 +50,11 @@ func List(ctx context.Context, options *ListOptions) ([]entities.ListContainer,
// used for more granular selection of containers. The main error returned indicates if there were runtime
// errors like finding containers. Errors specific to the removal of a container are in the PruneContainerResponse
// structure.
-func Prune(ctx context.Context, options *PruneOptions) (*entities.ContainerPruneReport, error) {
+func Prune(ctx context.Context, options *PruneOptions) ([]*reports.PruneReport, error) {
if options == nil {
options = new(PruneOptions)
}
- var reports *entities.ContainerPruneReport
+ var reports []*reports.PruneReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index 9beb493c8..ecdd1f553 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/podman/v2/pkg/auth"
"github.com/containers/podman/v2/pkg/bindings"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/pkg/errors"
)
@@ -163,9 +164,9 @@ func Export(ctx context.Context, nameOrIDs []string, w io.Writer, options *Expor
// Prune removes unused images from local storage. The optional filters can be used to further
// define which images should be pruned.
-func Prune(ctx context.Context, options *PruneOptions) ([]string, error) {
+func Prune(ctx context.Context, options *PruneOptions) ([]*reports.PruneReport, error) {
var (
- deleted []string
+ deleted []*reports.PruneReport
)
if options == nil {
options = new(PruneOptions)
@@ -182,7 +183,8 @@ func Prune(ctx context.Context, options *PruneOptions) ([]string, error) {
if err != nil {
return deleted, err
}
- return deleted, response.Process(&deleted)
+ err = response.Process(&deleted)
+ return deleted, err
}
// Tag adds an additional name to locally-stored image. Both the tag and repo parameters are required.
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 2ab5e45d0..fa601e7e5 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/bindings"
"github.com/containers/podman/v2/pkg/bindings/containers"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/specgen"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -533,8 +534,8 @@ var _ = Describe("Podman containers ", func() {
// Prune container should return no errors and one pruned container ID.
pruneResponse, err := containers.Prune(bt.conn, nil)
Expect(err).To(BeNil())
- Expect(len(pruneResponse.Err)).To(Equal(0))
- Expect(len(pruneResponse.ID)).To(Equal(1))
+ Expect(len(reports.PruneReportsErrs(pruneResponse))).To(Equal(0))
+ Expect(len(reports.PruneReportsIds(pruneResponse))).To(Equal(1))
})
It("podman prune stopped containers with filters", func() {
@@ -558,8 +559,8 @@ var _ = Describe("Podman containers ", func() {
}
pruneResponse, err = containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filtersIncorrect))
Expect(err).To(BeNil())
- Expect(len(pruneResponse.Err)).To(Equal(0))
- Expect(len(pruneResponse.ID)).To(Equal(0))
+ Expect(len(reports.PruneReportsIds(pruneResponse))).To(Equal(0))
+ Expect(len(reports.PruneReportsErrs(pruneResponse))).To(Equal(0))
// Valid filter params container should be pruned now.
filters := map[string][]string{
@@ -567,8 +568,8 @@ var _ = Describe("Podman containers ", func() {
}
pruneResponse, err = containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filters))
Expect(err).To(BeNil())
- Expect(len(pruneResponse.Err)).To(Equal(0))
- Expect(len(pruneResponse.ID)).To(Equal(1))
+ Expect(len(reports.PruneReportsErrs(pruneResponse))).To(Equal(0))
+ Expect(len(reports.PruneReportsIds(pruneResponse))).To(Equal(1))
})
It("podman prune running containers", func() {
@@ -585,7 +586,7 @@ var _ = Describe("Podman containers ", func() {
// Prune. Should return no error no prune response ID.
pruneResponse, err := containers.Prune(bt.conn, nil)
Expect(err).To(BeNil())
- Expect(len(pruneResponse.ID)).To(Equal(0))
+ Expect(len(pruneResponse)).To(Equal(0))
})
It("podman inspect bogus container", func() {
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index e178f4219..c6b9c20f9 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings"
"github.com/containers/podman/v2/pkg/bindings/containers"
"github.com/containers/podman/v2/pkg/bindings/images"
+ dreports "github.com/containers/podman/v2/pkg/domain/entities/reports"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
@@ -355,7 +356,7 @@ var _ = Describe("Podman images", func() {
results, err := images.Prune(bt.conn, options)
Expect(err).NotTo(HaveOccurred())
Expect(len(results)).To(BeNumerically(">", 0))
- Expect(results).To(ContainElement("docker.io/library/alpine:latest"))
+ Expect(dreports.PruneReportsIds(results)).To(ContainElement("docker.io/library/alpine:latest"))
})
// TODO: we really need to extent to pull tests once we have a more sophisticated CI.
diff --git a/pkg/bindings/test/system_test.go b/pkg/bindings/test/system_test.go
index 25fda5575..44067b61d 100644
--- a/pkg/bindings/test/system_test.go
+++ b/pkg/bindings/test/system_test.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings/system"
"github.com/containers/podman/v2/pkg/bindings/volumes"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
@@ -80,12 +81,12 @@ var _ = Describe("Podman system", func() {
systemPruneResponse, err := system.Prune(bt.conn, options)
Expect(err).To(BeNil())
Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(1))
- Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1))
- Expect(len(systemPruneResponse.ImagePruneReport.Report.Id)).
+ Expect(len(systemPruneResponse.ContainerPruneReports)).To(Equal(1))
+ Expect(len(systemPruneResponse.ImagePruneReports)).
To(BeNumerically(">", 0))
- Expect(systemPruneResponse.ImagePruneReport.Report.Id).
+ Expect(reports.PruneReportsIds(systemPruneResponse.ImagePruneReports)).
To(ContainElement("docker.io/library/alpine:latest"))
- Expect(len(systemPruneResponse.VolumePruneReport)).To(Equal(0))
+ Expect(len(systemPruneResponse.VolumePruneReports)).To(Equal(0))
})
It("podman system prune running alpine container", func() {
@@ -114,14 +115,14 @@ var _ = Describe("Podman system", func() {
systemPruneResponse, err := system.Prune(bt.conn, options)
Expect(err).To(BeNil())
Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(1))
- Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1))
- Expect(len(systemPruneResponse.ImagePruneReport.Report.Id)).
+ Expect(len(systemPruneResponse.ContainerPruneReports)).To(Equal(1))
+ Expect(len(systemPruneResponse.ImagePruneReports)).
To(BeNumerically(">", 0))
// Alpine image should not be pruned as used by running container
- Expect(systemPruneResponse.ImagePruneReport.Report.Id).
+ Expect(reports.PruneReportsIds(systemPruneResponse.ImagePruneReports)).
ToNot(ContainElement("docker.io/library/alpine:latest"))
// Though unused volume is available it should not be pruned as flag set to false.
- Expect(len(systemPruneResponse.VolumePruneReport)).To(Equal(0))
+ Expect(len(systemPruneResponse.VolumePruneReports)).To(Equal(0))
})
It("podman system prune running alpine container volume prune", func() {
@@ -149,14 +150,14 @@ var _ = Describe("Podman system", func() {
systemPruneResponse, err := system.Prune(bt.conn, options)
Expect(err).To(BeNil())
Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(0))
- Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1))
- Expect(len(systemPruneResponse.ImagePruneReport.Report.Id)).
+ Expect(len(systemPruneResponse.ContainerPruneReports)).To(Equal(1))
+ Expect(len(systemPruneResponse.ImagePruneReports)).
To(BeNumerically(">", 0))
// Alpine image should not be pruned as used by running container
- Expect(systemPruneResponse.ImagePruneReport.Report.Id).
+ Expect(reports.PruneReportsIds(systemPruneResponse.ImagePruneReports)).
ToNot(ContainElement("docker.io/library/alpine:latest"))
// Volume should be pruned now as flag set true
- Expect(len(systemPruneResponse.VolumePruneReport)).To(Equal(1))
+ Expect(len(systemPruneResponse.VolumePruneReports)).To(Equal(1))
})
It("podman system prune running alpine container volume prune --filter", func() {
@@ -197,14 +198,14 @@ var _ = Describe("Podman system", func() {
// This check **should** be "Equal(0)" since we are passing label
// filters however the Prune function doesn't seem to pass filters
// to each component.
- Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1))
- Expect(len(systemPruneResponse.ImagePruneReport.Report.Id)).
+ Expect(len(systemPruneResponse.ContainerPruneReports)).To(Equal(1))
+ Expect(len(systemPruneResponse.ImagePruneReports)).
To(BeNumerically(">", 0))
// Alpine image should not be pruned as used by running container
- Expect(systemPruneResponse.ImagePruneReport.Report.Id).
+ Expect(reports.PruneReportsIds(systemPruneResponse.ImagePruneReports)).
ToNot(ContainElement("docker.io/library/alpine:latest"))
// Volume shouldn't be pruned because the PruneOptions filters doesn't match
- Expect(len(systemPruneResponse.VolumePruneReport)).To(Equal(0))
+ Expect(len(systemPruneResponse.VolumePruneReports)).To(Equal(0))
// Fix filter and re prune
f["label"] = []string{"label1=value1"}
@@ -213,6 +214,6 @@ var _ = Describe("Podman system", func() {
Expect(err).To(BeNil())
// Volume should be pruned because the PruneOptions filters now match
- Expect(len(systemPruneResponse.VolumePruneReport)).To(Equal(1))
+ Expect(len(systemPruneResponse.VolumePruneReports)).To(Equal(1))
})
})
diff --git a/pkg/bindings/test/volumes_test.go b/pkg/bindings/test/volumes_test.go
index e0d854b66..1f1da3cfa 100644
--- a/pkg/bindings/test/volumes_test.go
+++ b/pkg/bindings/test/volumes_test.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings/containers"
"github.com/containers/podman/v2/pkg/bindings/volumes"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
@@ -166,7 +167,7 @@ var _ = Describe("Podman volumes", func() {
session.Wait(45)
vols, err = volumes.Prune(connText, nil)
Expect(err).To(BeNil())
- Expect(len(vols)).To(BeNumerically("==", 1))
+ Expect(len(reports.PruneReportsIds(vols))).To(BeNumerically("==", 1))
_, err = volumes.Inspect(connText, "homer", nil)
Expect(err).To(BeNil())
diff --git a/pkg/bindings/volumes/volumes.go b/pkg/bindings/volumes/volumes.go
index 626f52d39..fe081eb46 100644
--- a/pkg/bindings/volumes/volumes.go
+++ b/pkg/bindings/volumes/volumes.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
jsoniter "github.com/json-iterator/go"
)
@@ -77,9 +78,9 @@ func List(ctx context.Context, options *ListOptions) ([]*entities.VolumeListRepo
}
// Prune removes unused volumes from the local filesystem.
-func Prune(ctx context.Context, options *PruneOptions) ([]*entities.VolumePruneReport, error) {
+func Prune(ctx context.Context, options *PruneOptions) ([]*reports.PruneReport, error) {
var (
- pruned []*entities.VolumePruneReport
+ pruned []*reports.PruneReport
)
conn, err := bindings.GetClient(ctx)
if err != nil {
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index b8d49d067..05b9b774e 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -390,13 +390,6 @@ type ContainerPruneOptions struct {
Filters url.Values `json:"filters" schema:"filters"`
}
-// ContainerPruneReport describes the results after pruning the
-// stopped containers.
-type ContainerPruneReport struct {
- ID map[string]int64
- Err map[string]error
-}
-
// ContainerPortOptions describes the options to obtain
// port information on containers
type ContainerPortOptions struct {
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 80127ea45..7d38a97f2 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/specgen"
"github.com/spf13/cobra"
)
@@ -35,7 +36,7 @@ type ContainerEngine interface {
ContainerMount(ctx context.Context, nameOrIDs []string, options ContainerMountOptions) ([]*ContainerMountReport, error)
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerPort(ctx context.Context, nameOrID string, options ContainerPortOptions) ([]*ContainerPortReport, error)
- ContainerPrune(ctx context.Context, options ContainerPruneOptions) (*ContainerPruneReport, error)
+ ContainerPrune(ctx context.Context, options ContainerPruneOptions) ([]*reports.PruneReport, error)
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
ContainerRestore(ctx context.Context, namesOrIds []string, options RestoreOptions) ([]*RestoreReport, error)
ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
@@ -85,6 +86,6 @@ type ContainerEngine interface {
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IDOrNameResponse, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts InspectOptions) ([]*VolumeInspectReport, []error, error)
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
- VolumePrune(ctx context.Context, options VolumePruneOptions) ([]*VolumePruneReport, error)
+ VolumePrune(ctx context.Context, options VolumePruneOptions) ([]*reports.PruneReport, error)
VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)
}
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go
index 7f33d8e9d..26a136f13 100644
--- a/pkg/domain/entities/engine_image.go
+++ b/pkg/domain/entities/engine_image.go
@@ -4,6 +4,7 @@ import (
"context"
"github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
)
type ImageEngine interface {
@@ -17,7 +18,7 @@ type ImageEngine interface {
List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error)
Load(ctx context.Context, opts ImageLoadOptions) (*ImageLoadReport, error)
Mount(ctx context.Context, images []string, options ImageMountOptions) ([]*ImageMountReport, error)
- Prune(ctx context.Context, opts ImagePruneOptions) (*ImagePruneReport, error)
+ Prune(ctx context.Context, opts ImagePruneOptions) ([]*reports.PruneReport, error)
Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error)
Push(ctx context.Context, source string, destination string, opts ImagePushOptions) error
Remove(ctx context.Context, images []string, opts ImageRemoveOptions) (*ImageRemoveReport, []error)
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 67910a34c..d5f88502a 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -247,11 +247,6 @@ type ImagePruneOptions struct {
Filter []string `json:"filter" schema:"filter"`
}
-type ImagePruneReport struct {
- Report Report
- Size int64
-}
-
type ImageTagOptions struct{}
type ImageUntagOptions struct{}
diff --git a/pkg/domain/entities/reports/prune.go b/pkg/domain/entities/reports/prune.go
new file mode 100644
index 000000000..5494ac3ae
--- /dev/null
+++ b/pkg/domain/entities/reports/prune.go
@@ -0,0 +1,40 @@
+package reports
+
+type PruneReport struct {
+ Id string //nolint
+ Err error
+ Size uint64
+}
+
+func PruneReportsIds(r []*PruneReport) []string {
+ ids := make([]string, 0, len(r))
+ for _, v := range r {
+ if v == nil || v.Id == "" {
+ continue
+ }
+ ids = append(ids, v.Id)
+ }
+ return ids
+}
+
+func PruneReportsErrs(r []*PruneReport) []error {
+ errs := make([]error, 0, len(r))
+ for _, v := range r {
+ if v == nil || v.Err == nil {
+ continue
+ }
+ errs = append(errs, v.Err)
+ }
+ return errs
+}
+
+func PruneReportsSize(r []*PruneReport) uint64 {
+ size := uint64(0)
+ for _, v := range r {
+ if v == nil {
+ continue
+ }
+ size = size + v.Size
+ }
+ return size
+}
diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go
index d5118f6a8..99fa947f0 100644
--- a/pkg/domain/entities/system.go
+++ b/pkg/domain/entities/system.go
@@ -4,6 +4,7 @@ import (
"time"
"github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/docker/docker/api/types"
"github.com/spf13/cobra"
)
@@ -24,10 +25,11 @@ type SystemPruneOptions struct {
// SystemPruneReport provides report after system prune is executed.
type SystemPruneReport struct {
- PodPruneReport []*PodPruneReport
- *ContainerPruneReport
- *ImagePruneReport
- VolumePruneReport []*VolumePruneReport
+ PodPruneReport []*PodPruneReport
+ ContainerPruneReports []*reports.PruneReport
+ ImagePruneReports []*reports.PruneReport
+ VolumePruneReports []*reports.PruneReport
+ ReclaimedSpace uint64
}
// SystemMigrateOptions describes the options needed for the
diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go
index e6b29e374..06438f5e9 100644
--- a/pkg/domain/entities/volumes.go
+++ b/pkg/domain/entities/volumes.go
@@ -116,11 +116,6 @@ type VolumePruneOptions struct {
Filters url.Values `json:"filters" schema:"filters"`
}
-type VolumePruneReport struct {
- Err error
- Id string //nolint
-}
-
type VolumeListOptions struct {
Filter map[string][]string
}
diff --git a/libpod/filters/containers.go b/pkg/domain/filters/containers.go
index 505429de6..ce6c12b71 100644
--- a/libpod/filters/containers.go
+++ b/pkg/domain/filters/containers.go
@@ -1,4 +1,4 @@
-package lpfilters
+package filters
import (
"strconv"
@@ -233,7 +233,6 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
}
return false
}, nil
-
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
diff --git a/libpod/filters/pods.go b/pkg/domain/filters/pods.go
index 17b3f3ca9..7e6b7f2cc 100644
--- a/libpod/filters/pods.go
+++ b/pkg/domain/filters/pods.go
@@ -1,4 +1,4 @@
-package lpfilters
+package filters
import (
"strconv"
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index efb4f866f..9d7c2daea 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -16,12 +16,13 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/libpod/logs"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/checkpoint"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
+ dfilters "github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/domain/infra/abi/terminal"
parallelctr "github.com/containers/podman/v2/pkg/parallel/ctr"
"github.com/containers/podman/v2/pkg/ps"
@@ -204,28 +205,16 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
return reports, nil
}
-func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) {
+func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) ([]*reports.PruneReport, error) {
filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters))
for k, v := range options.Filters {
- generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod)
+ generatedFunc, err := dfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod)
if err != nil {
return nil, err
}
filterFuncs = append(filterFuncs, generatedFunc)
}
- return ic.pruneContainersHelper(filterFuncs)
-}
-
-func (ic *ContainerEngine) pruneContainersHelper(filterFuncs []libpod.ContainerFilter) (*entities.ContainerPruneReport, error) {
- prunedContainers, pruneErrors, err := ic.Libpod.PruneContainers(filterFuncs)
- if err != nil {
- return nil, err
- }
- report := entities.ContainerPruneReport{
- ID: prunedContainers,
- Err: pruneErrors,
- }
- return &report, nil
+ return ic.Libpod.PruneContainers(filterFuncs)
}
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 394ba359c..19f081abb 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -24,6 +24,7 @@ import (
"github.com/containers/podman/v2/libpod/image"
libpodImage "github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
domainUtils "github.com/containers/podman/v2/pkg/domain/utils"
"github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/podman/v2/pkg/util"
@@ -49,19 +50,12 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo
return &entities.BoolReport{Value: err == nil}, nil
}
-func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) (*entities.ImagePruneReport, error) {
- results, err := ir.Libpod.ImageRuntime().PruneImages(ctx, opts.All, opts.Filter)
+func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) ([]*reports.PruneReport, error) {
+ reports, err := ir.Libpod.ImageRuntime().PruneImages(ctx, opts.All, opts.Filter)
if err != nil {
return nil, err
}
-
- report := entities.ImagePruneReport{
- Report: entities.Report{
- Id: results,
- Err: nil,
- },
- }
- return &report, nil
+ return reports, err
}
func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entities.ImageHistoryOptions) (*entities.ImageHistoryReport, error) {
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 4135e8882..cbc74a2f2 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -226,7 +226,19 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, err
}
- specGen, err := kube.ToSpecGen(ctx, container, container.Image, newImage, volumes, pod.ID(), podName, podInfraID, configMaps, seccompPaths, ctrRestartPolicy, p.NetNS.IsHost())
+ specgenOpts := kube.CtrSpecGenOptions{
+ Container: container,
+ Image: newImage,
+ Volumes: volumes,
+ PodID: pod.ID(),
+ PodName: podName,
+ PodInfraID: podInfraID,
+ ConfigMaps: configMaps,
+ SeccompPaths: seccompPaths,
+ RestartPolicy: ctrRestartPolicy,
+ NetNSIsHost: p.NetNS.IsHost(),
+ }
+ specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 11374e513..f108b770c 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -5,8 +5,8 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/pkg/domain/entities"
+ dfilters "github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/signal"
"github.com/containers/podman/v2/pkg/specgen"
"github.com/containers/podman/v2/pkg/specgen/generate"
@@ -288,7 +288,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
filters := make([]libpod.PodFilter, 0, len(options.Filters))
for k, v := range options.Filters {
- f, err := lpfilters.GeneratePodFilterFunc(k, v)
+ f, err := dfilters.GeneratePodFilterFunc(k, v)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 5f6c95d4f..67c018122 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -16,6 +16,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/podman/v2/pkg/util"
"github.com/containers/podman/v2/utils"
@@ -170,6 +171,7 @@ func checkInput() error { // nolint:deadcode,unused
func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) {
var systemPruneReport = new(entities.SystemPruneReport)
var filters []string
+ reclaimedSpace := (uint64)(0)
found := true
for found {
found = false
@@ -186,42 +188,26 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
containerPruneOptions := entities.ContainerPruneOptions{}
containerPruneOptions.Filters = (url.Values)(options.Filters)
- containerPruneReport, err := ic.ContainerPrune(ctx, containerPruneOptions)
+ containerPruneReports, err := ic.ContainerPrune(ctx, containerPruneOptions)
if err != nil {
return nil, err
}
- if len(containerPruneReport.ID) > 0 {
- found = true
- }
- if systemPruneReport.ContainerPruneReport == nil {
- systemPruneReport.ContainerPruneReport = containerPruneReport
- } else {
- for name, val := range containerPruneReport.ID {
- systemPruneReport.ContainerPruneReport.ID[name] = val
- }
- }
+ reclaimedSpace = reclaimedSpace + reports.PruneReportsSize(containerPruneReports)
+ systemPruneReport.ContainerPruneReports = append(systemPruneReport.ContainerPruneReports, containerPruneReports...)
for k, v := range options.Filters {
filters = append(filters, fmt.Sprintf("%s=%s", k, v[0]))
}
- results, err := ic.Libpod.ImageRuntime().PruneImages(ctx, options.All, filters)
+ imagePruneReports, err := ic.Libpod.ImageRuntime().PruneImages(ctx, options.All, filters)
+ reclaimedSpace = reclaimedSpace + reports.PruneReportsSize(imagePruneReports)
if err != nil {
return nil, err
}
- if len(results) > 0 {
+ if len(imagePruneReports) > 0 {
found = true
}
- if systemPruneReport.ImagePruneReport == nil {
- systemPruneReport.ImagePruneReport = &entities.ImagePruneReport{
- Report: entities.Report{
- Id: results,
- Err: nil,
- },
- }
- } else {
- systemPruneReport.ImagePruneReport.Report.Id = append(systemPruneReport.ImagePruneReport.Report.Id, results...)
- }
+ systemPruneReport.ImagePruneReports = append(systemPruneReport.ImagePruneReports, imagePruneReports...)
if options.Volume {
volumePruneOptions := entities.VolumePruneOptions{}
volumePruneOptions.Filters = (url.Values)(options.Filters)
@@ -232,9 +218,11 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
if len(volumePruneReport) > 0 {
found = true
}
- systemPruneReport.VolumePruneReport = append(systemPruneReport.VolumePruneReport, volumePruneReport...)
+ reclaimedSpace = reclaimedSpace + reports.PruneReportsSize(volumePruneReport)
+ systemPruneReport.VolumePruneReports = append(systemPruneReport.VolumePruneReports, volumePruneReport...)
}
}
+ systemPruneReport.ReclaimedSpace = reclaimedSpace
return systemPruneReport, nil
}
diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go
index 515e52754..3c9dd9fc0 100644
--- a/pkg/domain/infra/abi/volumes.go
+++ b/pkg/domain/infra/abi/volumes.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/domain/infra/abi/parse"
"github.com/pkg/errors"
@@ -127,7 +128,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
return reports, errs, nil
}
-func (ic *ContainerEngine) VolumePrune(ctx context.Context, options entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) {
+func (ic *ContainerEngine) VolumePrune(ctx context.Context, options entities.VolumePruneOptions) ([]*reports.PruneReport, error) {
filterFuncs, err := filters.GenerateVolumeFilters(options.Filters)
if err != nil {
return nil, err
@@ -135,19 +136,12 @@ func (ic *ContainerEngine) VolumePrune(ctx context.Context, options entities.Vol
return ic.pruneVolumesHelper(ctx, filterFuncs)
}
-func (ic *ContainerEngine) pruneVolumesHelper(ctx context.Context, filterFuncs []libpod.VolumeFilter) ([]*entities.VolumePruneReport, error) {
+func (ic *ContainerEngine) pruneVolumesHelper(ctx context.Context, filterFuncs []libpod.VolumeFilter) ([]*reports.PruneReport, error) {
pruned, err := ic.Libpod.PruneVolumes(ctx, filterFuncs)
if err != nil {
return nil, err
}
- reports := make([]*entities.VolumePruneReport, 0, len(pruned))
- for k, v := range pruned {
- reports = append(reports, &entities.VolumePruneReport{
- Err: v,
- Id: k,
- })
- }
- return reports, nil
+ return pruned, nil
}
func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeListOptions) ([]*entities.VolumeListReport, error) {
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 0db985dff..3366cb425 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -18,6 +18,7 @@ import (
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/bindings/containers"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/errorhandling"
"github.com/containers/podman/v2/pkg/specgen"
"github.com/containers/podman/v2/pkg/util"
@@ -196,7 +197,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
return reports, nil
}
-func (ic *ContainerEngine) ContainerPrune(ctx context.Context, opts entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) {
+func (ic *ContainerEngine) ContainerPrune(ctx context.Context, opts entities.ContainerPruneOptions) ([]*reports.PruneReport, error) {
options := new(containers.PruneOptions).WithFilters(opts.Filters)
return containers.Prune(ic.ClientCtx, options)
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 10bf9682c..fba60235e 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -16,6 +16,7 @@ import (
"github.com/containers/image/v5/docker/reference"
images "github.com/containers/podman/v2/pkg/bindings/images"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/domain/utils"
utils2 "github.com/containers/podman/v2/utils"
"github.com/pkg/errors"
@@ -90,26 +91,18 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entiti
return &history, nil
}
-func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) (*entities.ImagePruneReport, error) {
+func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) ([]*reports.PruneReport, error) {
filters := make(map[string][]string, len(opts.Filter))
for _, filter := range opts.Filter {
f := strings.Split(filter, "=")
filters[f[0]] = f[1:]
}
options := new(images.PruneOptions).WithAll(opts.All).WithFilters(filters)
- results, err := images.Prune(ir.ClientCtx, options)
+ reports, err := images.Prune(ir.ClientCtx, options)
if err != nil {
return nil, err
}
-
- report := entities.ImagePruneReport{
- Report: entities.Report{
- Id: results,
- Err: nil,
- },
- Size: 0,
- }
- return &report, nil
+ return reports, nil
}
func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, opts entities.ImagePullOptions) (*entities.ImagePullReport, error) {
diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go
index e6ad4e0c5..10e8d7da8 100644
--- a/pkg/domain/infra/tunnel/volumes.go
+++ b/pkg/domain/infra/tunnel/volumes.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings/volumes"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/pkg/errors"
)
@@ -69,7 +70,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
return reports, errs, nil
}
-func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) {
+func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.VolumePruneOptions) ([]*reports.PruneReport, error) {
options := new(volumes.PruneOptions).WithFilters(opts.Filters)
return volumes.Prune(ic.ClientCtx, options)
}
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index 6c26e8708..9e0dcb728 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -11,8 +11,8 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/filters"
psdefine "github.com/containers/podman/v2/pkg/ps/define"
"github.com/containers/storage"
"github.com/pkg/errors"
@@ -27,7 +27,7 @@ func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOp
all := options.All || options.Last > 0
if len(options.Filters) > 0 {
for k, v := range options.Filters {
- generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, v, runtime)
+ generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime)
if err != nil {
return nil, err
}
@@ -41,7 +41,7 @@ func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOp
all = true
}
if !all {
- runningOnly, err := lpfilters.GenerateContainerFilterFuncs("status", []string{define.ContainerStateRunning.String()}, runtime)
+ runningOnly, err := filters.GenerateContainerFilterFuncs("status", []string{define.ContainerStateRunning.String()}, runtime)
if err != nil {
return nil, err
}
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index b5956029e..e5b09dcd8 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -47,30 +47,53 @@ func ToPodGen(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec)
return p, nil
}
-func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newImage *image.Image, volumes map[string]*KubeVolume, podID, podName, infraID string, configMaps []v1.ConfigMap, seccompPaths *KubeSeccompPaths, restartPolicy string, hostNet bool) (*specgen.SpecGenerator, error) {
- s := specgen.NewSpecGenerator(iid, false)
+type CtrSpecGenOptions struct {
+ // Container as read from the pod yaml
+ Container v1.Container
+ // Image available to use (pulled or found local)
+ Image *image.Image
+ // Volumes for all containers
+ Volumes map[string]*KubeVolume
+ // PodID of the parent pod
+ PodID string
+ // PodName of the parent pod
+ PodName string
+ // PodInfraID as the infrastructure container id
+ PodInfraID string
+ // ConfigMaps the configuration maps for environment variables
+ ConfigMaps []v1.ConfigMap
+ // SeccompPaths for finding the seccomp profile path
+ SeccompPaths *KubeSeccompPaths
+ // RestartPolicy defines the restart policy of the container
+ RestartPolicy string
+ // NetNSIsHost tells the container to use the host netns
+ NetNSIsHost bool
+}
+
+func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) {
+ s := specgen.NewSpecGenerator(opts.Container.Image, false)
- // podName should be non-empty for Deployment objects to be able to create
+ // pod name should be non-empty for Deployment objects to be able to create
// multiple pods having containers with unique names
- if len(podName) < 1 {
- return nil, errors.Errorf("kubeContainerToCreateConfig got empty podName")
+ if len(opts.PodName) < 1 {
+ return nil, errors.Errorf("got empty pod name on container creation when playing kube")
}
- s.Name = fmt.Sprintf("%s-%s", podName, containerYAML.Name)
+ s.Name = fmt.Sprintf("%s-%s", opts.PodName, opts.Container.Name)
- s.Terminal = containerYAML.TTY
+ s.Terminal = opts.Container.TTY
- s.Pod = podID
+ s.Pod = opts.PodID
- setupSecurityContext(s, containerYAML)
+ setupSecurityContext(s, opts.Container)
// Since we prefix the container name with pod name to work-around the uniqueness requirement,
// the seccomp profile should reference the actual container name from the YAML
// but apply to the containers with the prefixed name
- s.SeccompProfilePath = seccompPaths.FindForContainer(containerYAML.Name)
+ s.SeccompProfilePath = opts.SeccompPaths.FindForContainer(opts.Container.Name)
s.ResourceLimits = &spec.LinuxResources{}
- milliCPU, err := quantityToInt64(containerYAML.Resources.Limits.Cpu())
+ milliCPU, err := quantityToInt64(opts.Container.Resources.Limits.Cpu())
if err != nil {
return nil, errors.Wrap(err, "Failed to set CPU quota")
}
@@ -82,12 +105,12 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
}
}
- limit, err := quantityToInt64(containerYAML.Resources.Limits.Memory())
+ limit, err := quantityToInt64(opts.Container.Resources.Limits.Memory())
if err != nil {
return nil, errors.Wrap(err, "Failed to set memory limit")
}
- memoryRes, err := quantityToInt64(containerYAML.Resources.Requests.Memory())
+ memoryRes, err := quantityToInt64(opts.Container.Resources.Requests.Memory())
if err != nil {
return nil, errors.Wrap(err, "Failed to set memory reservation")
}
@@ -107,7 +130,7 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
// TODO: We don't understand why specgen does not take of this, but
// integration tests clearly pointed out that it was required.
s.Command = []string{}
- imageData, err := newImage.Inspect(ctx)
+ imageData, err := opts.Image.Inspect(ctx)
if err != nil {
return nil, err
}
@@ -134,26 +157,26 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
}
}
// If only the yaml.Command is specified, set it as the entrypoint and drop the image Cmd
- if len(containerYAML.Command) != 0 {
- entrypoint = containerYAML.Command
+ if len(opts.Container.Command) != 0 {
+ entrypoint = opts.Container.Command
cmd = []string{}
}
// Only override the cmd field if yaml.Args is specified
// Keep the image entrypoint, or the yaml.command if specified
- if len(containerYAML.Args) != 0 {
- cmd = containerYAML.Args
+ if len(opts.Container.Args) != 0 {
+ cmd = opts.Container.Args
}
s.Command = append(entrypoint, cmd...)
// FIXME,
// we are currently ignoring imageData.Config.ExposedPorts
- if containerYAML.WorkingDir != "" {
- s.WorkDir = containerYAML.WorkingDir
+ if opts.Container.WorkingDir != "" {
+ s.WorkDir = opts.Container.WorkingDir
}
annotations := make(map[string]string)
- if infraID != "" {
- annotations[ann.SandboxID] = infraID
+ if opts.PodInfraID != "" {
+ annotations[ann.SandboxID] = opts.PodInfraID
annotations[ann.ContainerType] = ann.ContainerTypeContainer
}
s.Annotations = annotations
@@ -165,13 +188,13 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
envs[keyval[0]] = keyval[1]
}
- for _, env := range containerYAML.Env {
- value := envVarValue(env, configMaps)
+ for _, env := range opts.Container.Env {
+ value := envVarValue(env, opts.ConfigMaps)
envs[env.Name] = value
}
- for _, envFrom := range containerYAML.EnvFrom {
- cmEnvs := envVarsFromConfigMap(envFrom, configMaps)
+ for _, envFrom := range opts.Container.EnvFrom {
+ cmEnvs := envVarsFromConfigMap(envFrom, opts.ConfigMaps)
for k, v := range cmEnvs {
envs[k] = v
@@ -179,8 +202,8 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
}
s.Env = envs
- for _, volume := range containerYAML.VolumeMounts {
- volumeSource, exists := volumes[volume.Name]
+ for _, volume := range opts.Container.VolumeMounts {
+ volumeSource, exists := opts.Volumes[volume.Name]
if !exists {
return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
}
@@ -212,9 +235,9 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
}
}
- s.RestartPolicy = restartPolicy
+ s.RestartPolicy = opts.RestartPolicy
- if hostNet {
+ if opts.NetNSIsHost {
s.NetNS.NSMode = specgen.Host
}
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index 036c7b7a1..3cd5a3c9c 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -364,7 +364,9 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
// namespaces?
g.SetHostname(hostname)
}
- g.AddProcessEnv("HOSTNAME", hostname)
+ if _, ok := s.Env["HOSTNAME"]; !ok && s.Hostname != "" {
+ g.AddProcessEnv("HOSTNAME", hostname)
+ }
// User
switch s.UserNS.NSMode {
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index 0c97dc496..9fceec7b3 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -172,12 +172,16 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
// Clear default Seccomp profile from Generator for unconfined containers
// and privileged containers which do not specify a seccomp profile.
- if s.SeccompProfilePath == "unconfined" || (s.Privileged && (s.SeccompProfilePath == config.SeccompOverridePath || s.SeccompProfilePath == config.SeccompDefaultPath)) {
+ if s.SeccompProfilePath == "unconfined" || (s.Privileged && (s.SeccompProfilePath == "" || s.SeccompProfilePath == config.SeccompOverridePath || s.SeccompProfilePath == config.SeccompDefaultPath)) {
configSpec.Linux.Seccomp = nil
}
g.SetRootReadonly(s.ReadOnlyFilesystem)
+ noUseIPC := s.IpcNS.NSMode == specgen.FromContainer || s.IpcNS.NSMode == specgen.FromPod || s.IpcNS.NSMode == specgen.Host
+ noUseNet := s.NetNS.NSMode == specgen.FromContainer || s.NetNS.NSMode == specgen.FromPod || s.NetNS.NSMode == specgen.Host
+ noUseUTS := s.UtsNS.NSMode == specgen.FromContainer || s.UtsNS.NSMode == specgen.FromPod || s.UtsNS.NSMode == specgen.Host
+
// Add default sysctls
defaultSysctls, err := util.ValidateSysctls(rtc.Sysctls())
if err != nil {
@@ -186,20 +190,20 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
for sysctlKey, sysctlVal := range defaultSysctls {
// Ignore mqueue sysctls if --ipc=host
- if s.IpcNS.IsHost() && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
+ if noUseIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since IPC Namespace set to host", sysctlKey, sysctlVal)
continue
}
// Ignore net sysctls if --net=host
- if s.NetNS.IsHost() && strings.HasPrefix(sysctlKey, "net.") {
+ if noUseNet && strings.HasPrefix(sysctlKey, "net.") {
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace set to host", sysctlKey, sysctlVal)
continue
}
// Ignore uts sysctls if --uts=host
- if s.UtsNS.IsHost() && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) {
+ if noUseUTS && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) {
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since UTS Namespace set to host", sysctlKey, sysctlVal)
continue
}
diff --git a/pkg/systemd/generate/common.go b/pkg/systemd/generate/common.go
index 52a214883..fb921cd72 100644
--- a/pkg/systemd/generate/common.go
+++ b/pkg/systemd/generate/common.go
@@ -11,6 +11,11 @@ import (
// is set to the unit's (unique) name.
const EnvVariable = "PODMAN_SYSTEMD_UNIT"
+// minTimeoutStopSec is the minimal stop timeout for generated systemd units.
+// Once exceeded, processes of the services are killed and the cgroup(s) are
+// cleaned up.
+const minTimeoutStopSec = 60
+
// RestartPolicies includes all valid restart policies to be used in a unit
// file.
var RestartPolicies = []string{"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"}
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index d84125fc7..cfa02dc9d 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -55,6 +55,8 @@ type containerInfo struct {
ExecStartPre string
// ExecStart of the unit.
ExecStart string
+ // TimeoutStopSec of the unit.
+ TimeoutStopSec uint
// ExecStop of the unit.
ExecStop string
// ExecStopPost of the unit.
@@ -74,6 +76,7 @@ After={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $v
[Service]
Environment={{.EnvVariable}}=%n
Restart={{.RestartPolicy}}
+TimeoutStopSec={{.TimeoutStopSec}}
{{- if .ExecStartPre}}
ExecStartPre={{.ExecStartPre}}
{{- end}}
@@ -81,7 +84,6 @@ ExecStart={{.ExecStart}}
ExecStop={{.ExecStop}}
ExecStopPost={{.ExecStopPost}}
PIDFile={{.PIDFile}}
-KillMode=none
Type=forking
[Install]
@@ -255,6 +257,8 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst
info.ExecStopPost = "{{.Executable}} rm --ignore -f --cidfile {{.ContainerIDFile}}"
}
+ info.TimeoutStopSec = minTimeoutStopSec + info.StopTimeout
+
if info.PodmanVersion == "" {
info.PodmanVersion = version.Version.String()
}
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index d27062ef3..b9fb8fee6 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/stretchr/testify/assert"
)
func TestValidateRestartPolicyContainer(t *testing.T) {
@@ -48,11 +49,11 @@ After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=82
ExecStart=/usr/bin/podman start 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
-ExecStop=/usr/bin/podman stop -t 10 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
-ExecStopPost=/usr/bin/podman stop -t 10 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
+ExecStop=/usr/bin/podman stop -t 22 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
+ExecStopPost=/usr/bin/podman stop -t 22 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
Type=forking
[Install]
@@ -71,11 +72,11 @@ After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=70
ExecStart=/usr/bin/podman start foobar
ExecStop=/usr/bin/podman stop -t 10 foobar
ExecStopPost=/usr/bin/podman stop -t 10 foobar
PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
Type=forking
[Install]
@@ -96,11 +97,11 @@ After=a.service b.service c.service pod.service
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=70
ExecStart=/usr/bin/podman start foobar
ExecStop=/usr/bin/podman stop -t 10 foobar
ExecStopPost=/usr/bin/podman stop -t 10 foobar
PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
Type=forking
[Install]
@@ -119,12 +120,12 @@ After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon -d --replace --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN "foo=arg \"with \" space"
-ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 10
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
PIDFile=%t/jadda-jadda.pid
-KillMode=none
Type=forking
[Install]
@@ -143,12 +144,12 @@ After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon --replace -d --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
-ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 10
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
PIDFile=%t/jadda-jadda.pid
-KillMode=none
Type=forking
[Install]
@@ -167,12 +168,12 @@ After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon --pod-id-file /tmp/pod-foobar.pod-id-file --replace -d --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
-ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 10
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
PIDFile=%t/jadda-jadda.pid
-KillMode=none
Type=forking
[Install]
@@ -191,12 +192,12 @@ After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon --replace --detach --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
-ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 10
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
PIDFile=%t/jadda-jadda.pid
-KillMode=none
Type=forking
[Install]
@@ -215,12 +216,12 @@ After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id
ExecStart=/usr/bin/podman run --conmon-pidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid --cidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id --cgroups=no-conmon -d awesome-image:latest
ExecStop=/usr/bin/podman stop --ignore --cidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id -t 10
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id
PIDFile=%t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid
-KillMode=none
Type=forking
[Install]
@@ -242,7 +243,7 @@ WantedBy=multi-user.target default.target
ContainerNameOrID: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
RestartPolicy: "always",
PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
+ StopTimeout: 22,
PodmanVersion: "CI",
EnvVariable: EnvVariable,
},
@@ -302,7 +303,7 @@ WantedBy=multi-user.target default.target
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 42,
+ StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "container", "run", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN", "foo=arg \"with \" space"},
EnvVariable: EnvVariable,
@@ -318,7 +319,7 @@ WantedBy=multi-user.target default.target
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 42,
+ StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "container", "run", "-d", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
EnvVariable: EnvVariable,
@@ -334,7 +335,7 @@ WantedBy=multi-user.target default.target
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 42,
+ StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "container", "run", "-d", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
EnvVariable: EnvVariable,
@@ -353,7 +354,7 @@ WantedBy=multi-user.target default.target
ContainerNameOrID: "jadda-jadda",
RestartPolicy: "always",
PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 42,
+ StopTimeout: 10,
PodmanVersion: "CI",
CreateCommand: []string{"I'll get stripped", "container", "run", "--detach", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
EnvVariable: EnvVariable,
@@ -390,9 +391,7 @@ WantedBy=multi-user.target default.target
t.Errorf("CreateContainerSystemdUnit() error = \n%v, wantErr \n%v", err, test.wantErr)
return
}
- if got != test.want {
- t.Errorf("CreateContainerSystemdUnit() = \n%v\n---------> want\n%v", got, test.want)
- }
+ assert.Equal(t, test.want, got)
})
}
}
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index 3c57b03fb..fc582e42a 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -60,6 +60,8 @@ type podInfo struct {
ExecStartPre2 string
// ExecStart of the unit.
ExecStart string
+ // TimeoutStopSec of the unit.
+ TimeoutStopSec uint
// ExecStop of the unit.
ExecStop string
// ExecStopPost of the unit.
@@ -72,6 +74,7 @@ Before={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{
[Service]
Environment={{.EnvVariable}}=%n
Restart={{.RestartPolicy}}
+TimeoutStopSec={{.TimeoutStopSec}}
{{- if .ExecStartPre1}}
ExecStartPre={{.ExecStartPre1}}
{{- end}}
@@ -82,7 +85,6 @@ ExecStart={{.ExecStart}}
ExecStop={{.ExecStop}}
ExecStopPost={{.ExecStopPost}}
PIDFile={{.PIDFile}}
-KillMode=none
Type=forking
[Install]
@@ -298,6 +300,8 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions)
info.ExecStop = "{{.Executable}} pod stop --ignore --pod-id-file {{.PodIDFile}} {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}}"
info.ExecStopPost = "{{.Executable}} pod rm --ignore -f --pod-id-file {{.PodIDFile}}"
}
+ info.TimeoutStopSec = minTimeoutStopSec + info.StopTimeout
+
if info.PodmanVersion == "" {
info.PodmanVersion = version.Version.String()
}
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index 7f1f63b7e..6d925ecd2 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/stretchr/testify/assert"
)
func TestValidateRestartPolicyPod(t *testing.T) {
@@ -50,11 +51,11 @@ Before=container-1.service container-2.service
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
+TimeoutStopSec=102
ExecStart=/usr/bin/podman start jadda-jadda-infra
-ExecStop=/usr/bin/podman stop -t 10 jadda-jadda-infra
-ExecStopPost=/usr/bin/podman stop -t 10 jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
Type=forking
[Install]
@@ -75,13 +76,13 @@ Before=container-1.service container-2.service
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
+TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id
ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo "bar=arg with space" --replace
ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id
ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10
ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id
PIDFile=%t/pod-123abc.pid
-KillMode=none
Type=forking
[Install]
@@ -102,7 +103,7 @@ WantedBy=multi-user.target default.target
InfraNameOrID: "jadda-jadda-infra",
RestartPolicy: "always",
PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
+ StopTimeout: 42,
PodmanVersion: "CI",
RequiredServices: []string{"container-1", "container-2"},
},
@@ -139,9 +140,7 @@ WantedBy=multi-user.target default.target
t.Errorf("CreatePodSystemdUnit() error = \n%v, wantErr \n%v", err, test.wantErr)
return
}
- if got != test.want {
- t.Errorf("CreatePodSystemdUnit() = \n%v\n---------> want\n%v", got, test.want)
- }
+ assert.Equal(t, test.want, got)
})
}
}
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index bc6efc20d..decdc4754 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -203,6 +203,15 @@ t GET 'containers/json?limit=0&all=1' 200 \
.[0].Id~[0-9a-f]\\{64\\} \
.[1].Id~[0-9a-f]\\{64\\}
+t GET containers/json?limit=2 200 length=2
+
+# Filter with two ids should return both container
+t GET "containers/json?filters=%7B%22id%22%3A%5B%22${cid}%22%2C%22${cid_top}%22%5D%7D&all=1" 200 length=2
+# Filter with two ids and status running should return only 1 container
+t GET "containers/json?filters=%7B%22id%22%3A%5B%22${cid}%22%2C%22${cid_top}%22%5D%2C%22status%22%3A%5B%22running%22%5D%7D&all=1" 200 \
+ length=1 \
+ .[0].Id=${cid_top}
+
t POST containers/${cid_top}/stop "" 204
t DELETE containers/$cid 204
diff --git a/test/apiv2/45-system.at b/test/apiv2/45-system.at
index 7d14fd4b3..44cd05a13 100644
--- a/test/apiv2/45-system.at
+++ b/test/apiv2/45-system.at
@@ -58,10 +58,10 @@ t GET libpod/system/df 200 '.Volumes | length=3'
# -G --data-urlencode 'volumes=true&filters={"label":["testlabel1=testonly"]}'
# only foo3 should be pruned because of filter
-t POST 'libpod/system/prune?volumes=true&filters=%7B%22label%22:%5B%22testlabel1=testonly%22%5D%7D' params='' 200 .VolumePruneReport[0].Id=foo3
+t POST 'libpod/system/prune?volumes=true&filters=%7B%22label%22:%5B%22testlabel1=testonly%22%5D%7D' params='' 200 .VolumePruneReports[0].Id=foo3
# only foo2 should be pruned because of filter
-t POST 'libpod/system/prune?volumes=true&filters=%7B%22label%22:%5B%22testlabel1%22%5D%7D' params='' 200 .VolumePruneReport[0].Id=foo2
+t POST 'libpod/system/prune?volumes=true&filters=%7B%22label%22:%5B%22testlabel1%22%5D%7D' params='' 200 .VolumePruneReports[0].Id=foo2
# foo1, the last remaining volume should be pruned without any filters applied
-t POST 'libpod/system/prune?volumes=true' params='' 200 .VolumePruneReport[0].Id=foo1
+t POST 'libpod/system/prune?volumes=true' params='' 200 .VolumePruneReports[0].Id=foo1
# TODO add other system prune tests for pods / images
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index f61f52589..18737105e 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -119,6 +119,21 @@ var _ = Describe("Podman exec", func() {
Expect(session.ExitCode()).To(Equal(100))
})
+ It("podman exec --privileged", func() {
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
+
+ setup := podmanTest.RunTopContainer("test-privileged")
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
+ })
+
It("podman exec terminal doesn't hang", func() {
setup := podmanTest.Podman([]string{"run", "-dti", "--name", "test1", fedoraMinimal, "sleep", "+Inf"})
setup.WaitWithDefaultTimeout()
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 765844265..3f059300b 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -74,6 +74,9 @@ var _ = Describe("Podman generate systemd", func() {
found, _ := session.GrepString(" stop -t 1234 ")
Expect(found).To(BeTrue())
+
+ found, _ = session.GrepString("TimeoutStopSec=1294")
+ Expect(found).To(BeTrue())
})
It("podman generate systemd", func() {
diff --git a/test/e2e/pod_stats_test.go b/test/e2e/pod_stats_test.go
index a034ec2d1..287830102 100644
--- a/test/e2e/pod_stats_test.go
+++ b/test/e2e/pod_stats_test.go
@@ -177,8 +177,7 @@ var _ = Describe("Podman pod stats", func() {
It("podman stats on net=host post", func() {
// --net=host not supported for rootless pods at present
- // problem with sysctls being passed to containers of the pod.
- SkipIfCgroupV1("Bug: Error: sysctl net.ipv4.ping_group_range is not allowed in the hosts network namespace: OCI runtime error")
+ SkipIfRootlessCgroupsV1("Pause stats not supported in cgroups v1")
podName := "testPod"
podCreate := podmanTest.Podman([]string{"pod", "create", "--net=host", "--name", podName})
podCreate.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index 760de55b6..48f9ea76e 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -16,22 +16,22 @@ import (
// know about at compile time. That is: the kernel may have more caps
// available than we are aware of, leading to host=FFF... and ctr=3FF...
// because the latter is all we request. Accept that.
-func containerCapMatchesHost(ctr_cap string, host_cap string) {
+func containerCapMatchesHost(ctrCap string, hostCap string) {
if isRootless() {
return
}
- ctr_cap_n, err := strconv.ParseUint(ctr_cap, 16, 64)
- Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", ctr_cap)
+ ctrCap_n, err := strconv.ParseUint(ctrCap, 16, 64)
+ Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", ctrCap)
- host_cap_n, err := strconv.ParseUint(host_cap, 16, 64)
- Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", host_cap)
+ hostCap_n, err := strconv.ParseUint(hostCap, 16, 64)
+ Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", hostCap)
// host caps can never be zero (except rootless).
// and host caps must always be a superset (inclusive) of container
- Expect(host_cap_n).To(BeNumerically(">", 0), "host cap %q should be nonzero", host_cap)
- Expect(host_cap_n).To(BeNumerically(">=", ctr_cap_n), "host cap %q should never be less than container cap %q", host_cap, ctr_cap)
- host_cap_masked := host_cap_n & (1<<len(capability.List()) - 1)
- Expect(ctr_cap_n).To(Equal(host_cap_masked), "container cap %q is not a subset of host cap %q", ctr_cap, host_cap)
+ Expect(hostCap_n).To(BeNumerically(">", 0), "host cap %q should be nonzero", hostCap)
+ Expect(hostCap_n).To(BeNumerically(">=", ctrCap_n), "host cap %q should never be less than container cap %q", hostCap, ctrCap)
+ hostCap_masked := hostCap_n & (1<<len(capability.List()) - 1)
+ Expect(ctrCap_n).To(Equal(hostCap_masked), "container cap %q is not a subset of host cap %q", ctrCap, hostCap)
}
var _ = Describe("Podman privileged container tests", func() {
@@ -68,38 +68,38 @@ var _ = Describe("Podman privileged container tests", func() {
})
It("podman privileged CapEff", func() {
- host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
- Expect(host_cap.ExitCode()).To(Equal(0))
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"run", "--privileged", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
})
It("podman cap-add CapEff", func() {
// Get caps of current process
- host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
- Expect(host_cap.ExitCode()).To(Equal(0))
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"run", "--cap-add", "all", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
})
It("podman cap-add CapEff with --user", func() {
// Get caps of current process
- host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
- Expect(host_cap.ExitCode()).To(Equal(0))
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"run", "--user=bin", "--cap-add", "all", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
})
It("podman cap-drop CapEff", func() {
@@ -110,6 +110,15 @@ var _ = Describe("Podman privileged container tests", func() {
Expect("0000000000000000").To(Equal(capEff[1]))
})
+ It("podman privileged should disable seccomp by default", func() {
+ hostSeccomp := SystemExec("grep", []string{"-Ei", "^Seccomp:\\s+0$", "/proc/self/status"})
+ Expect(hostSeccomp.ExitCode()).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "grep", "-Ei", "^Seccomp:\\s+0$", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
It("podman non-privileged should have very few devices", func() {
session := podmanTest.Podman([]string{"run", "-t", "busybox", "ls", "-l", "/dev"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 4888a676b..92d7d222e 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -1415,4 +1415,12 @@ WORKDIR /madethis`
Expect(session.ExitCode()).To(Equal(0))
Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull"))
})
+
+ It("podman run container with hostname and hostname environment variable", func() {
+ hostnameEnv := "test123"
+ session := podmanTest.Podman([]string{"run", "--hostname", "testctr", "--env", fmt.Sprintf("HOSTNAME=%s", hostnameEnv), ALPINE, "printenv", "HOSTNAME"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(hostnameEnv))
+ })
})
diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go
index 48294943b..49ab3b8ed 100644
--- a/test/e2e/systemd_test.go
+++ b/test/e2e/systemd_test.go
@@ -13,10 +13,10 @@ import (
var _ = Describe("Podman systemd", func() {
var (
- tempdir string
- err error
- podmanTest *PodmanTestIntegration
- systemd_unit_file string
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ systemdUnitFile string
)
BeforeEach(func() {
@@ -27,7 +27,7 @@ var _ = Describe("Podman systemd", func() {
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
podmanTest.SeedImages()
- systemd_unit_file = `[Unit]
+ systemdUnitFile = `[Unit]
Description=redis container
[Service]
Restart=always
@@ -50,7 +50,7 @@ WantedBy=multi-user.target
SkipIfRootless("rootless can not write to /etc")
SkipIfContainerized("test does not have systemd as pid 1")
- sys_file := ioutil.WriteFile("/etc/systemd/system/redis.service", []byte(systemd_unit_file), 0644)
+ sys_file := ioutil.WriteFile("/etc/systemd/system/redis.service", []byte(systemdUnitFile), 0644)
Expect(sys_file).To(BeNil())
defer func() {
stop := SystemExec("bash", []string{"-c", "systemctl stop redis"})
@@ -131,6 +131,21 @@ WantedBy=multi-user.target
Expect(conData[0].Config.SystemdMode).To(BeTrue())
})
+ It("podman create container with --uidmap and conmon PidFile accessible", func() {
+ ctrName := "testCtrUidMap"
+ run := podmanTest.Podman([]string{"run", "-d", "--uidmap=0:1:1000", "--name", ctrName, ALPINE, "top"})
+ run.WaitWithDefaultTimeout()
+ Expect(run.ExitCode()).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"inspect", "--format", "{{.ConmonPidFile}}", ctrName})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ pidFile := strings.TrimSuffix(session.OutputToString(), "\n")
+ _, err := ioutil.ReadFile(pidFile)
+ Expect(err).To(BeNil())
+ })
+
It("podman create container with systemd=always triggers systemd mode", func() {
ctrName := "testCtr"
run := podmanTest.Podman([]string{"create", "--name", ctrName, "--systemd", "always", ALPINE})
diff --git a/vendor/github.com/containers/psgo/internal/capabilities/capabilities.go b/vendor/github.com/containers/psgo/internal/capabilities/capabilities.go
index c46468930..1a60b96c4 100644
--- a/vendor/github.com/containers/psgo/internal/capabilities/capabilities.go
+++ b/vendor/github.com/containers/psgo/internal/capabilities/capabilities.go
@@ -13,7 +13,7 @@
// limitations under the License.
// Package capabilities provides a mapping from common kernel bit masks to the
-// alphanumerical represenation of kernel capabilities. See capabilities(7)
+// alphanumerical representation of kernel capabilities. See capabilities(7)
// for additional information.
package capabilities
diff --git a/vendor/github.com/containers/psgo/internal/dev/tty.go b/vendor/github.com/containers/psgo/internal/dev/tty.go
index b7d6f28ac..863767f75 100644
--- a/vendor/github.com/containers/psgo/internal/dev/tty.go
+++ b/vendor/github.com/containers/psgo/internal/dev/tty.go
@@ -113,8 +113,9 @@ func TTYs() (*[]TTY, error) {
}
s := fi.Sys().(*syscall.Stat_t)
t := TTY{
- Minor: minDevNum(s.Rdev),
- Major: majDevNum(s.Rdev),
+ // Rdev is type uint32 on mips arch so we have to cast to uint64
+ Minor: minDevNum(uint64(s.Rdev)),
+ Major: majDevNum(uint64(s.Rdev)),
Path: dev,
}
ttys = append(ttys, t)
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index 29d059361..df31139f8 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -24,7 +24,7 @@ import (
"github.com/pkg/errors"
)
-// Status is a direct translation of a `/proc/[pid]/status`, wich provides much
+// Status is a direct translation of a `/proc/[pid]/status`, which provides much
// of the information in /proc/[pid]/stat and /proc/[pid]/statm in a format
// that's easier for humans to parse.
type Status struct {
diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go
index b46a39f46..a581921d5 100644
--- a/vendor/github.com/containers/psgo/internal/process/process.go
+++ b/vendor/github.com/containers/psgo/internal/process/process.go
@@ -31,9 +31,9 @@ type Process struct {
Pid string
// Stat contains data from /proc/$pid/stat.
Stat proc.Stat
- // Status containes data from /proc/$pid/status.
+ // Status contains data from /proc/$pid/status.
Status proc.Status
- // CmdLine containes data from /proc/$pid/cmdline.
+ // CmdLine contains data from /proc/$pid/cmdline.
CmdLine []string
// Label containers data from /proc/$pid/attr/current.
Label string
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index c75fc3815..7c74fd716 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -482,7 +482,7 @@ func JoinNamespaceAndProcessInfoByPidsWithOptions(pids []string, descriptors []s
// catch race conditions
continue
}
- return nil, errors.Wrapf(err, "error extracing PID namespace")
+ return nil, errors.Wrapf(err, "error extracting PID namespace")
}
if _, exists := nsMap[ns]; !exists {
nsMap[ns] = true
@@ -759,7 +759,7 @@ func processVSZ(p *process.Process, ctx *psContext) (string, error) {
}
// parseCAP parses cap (a string bit mask) and returns the associated set of
-// capabilities. If all capabilties are set, "full" is returned. If no
+// capabilities. If all capabilities are set, "full" is returned. If no
// capability is enabled, "none" is returned.
func parseCAP(cap string) (string, error) {
mask, err := strconv.ParseUint(cap, 16, 64)
@@ -777,36 +777,36 @@ func parseCAP(cap string) (string, error) {
return strings.Join(caps, ","), nil
}
-// processCAPAMB returns the set of ambient capabilties associated with
-// process p. If all capabilties are set, "full" is returned. If no
+// processCAPAMB returns the set of ambient capabilities associated with
+// process p. If all capabilities are set, "full" is returned. If no
// capability is enabled, "none" is returned.
func processCAPAMB(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapAmb)
}
-// processCAPINH returns the set of inheritable capabilties associated with
-// process p. If all capabilties are set, "full" is returned. If no
+// processCAPINH returns the set of inheritable capabilities associated with
+// process p. If all capabilities are set, "full" is returned. If no
// capability is enabled, "none" is returned.
func processCAPINH(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapInh)
}
-// processCAPPRM returns the set of permitted capabilties associated with
-// process p. If all capabilties are set, "full" is returned. If no
+// processCAPPRM returns the set of permitted capabilities associated with
+// process p. If all capabilities are set, "full" is returned. If no
// capability is enabled, "none" is returned.
func processCAPPRM(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapPrm)
}
-// processCAPEFF returns the set of effective capabilties associated with
-// process p. If all capabilties are set, "full" is returned. If no
+// processCAPEFF returns the set of effective capabilities associated with
+// process p. If all capabilities are set, "full" is returned. If no
// capability is enabled, "none" is returned.
func processCAPEFF(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapEff)
}
-// processCAPBND returns the set of bounding capabilties associated with
-// process p. If all capabilties are set, "full" is returned. If no
+// processCAPBND returns the set of bounding capabilities associated with
+// process p. If all capabilities are set, "full" is returned. If no
// capability is enabled, "none" is returned.
func processCAPBND(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapBnd)
diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go
index 524404cc5..daf3639c1 100644
--- a/vendor/github.com/google/uuid/uuid.go
+++ b/vendor/github.com/google/uuid/uuid.go
@@ -35,6 +35,12 @@ const (
var rander = rand.Reader // random function
+type invalidLengthError struct{ len int }
+
+func (err *invalidLengthError) Error() string {
+ return fmt.Sprintf("invalid UUID length: %d", err.len)
+}
+
// Parse decodes s into a UUID or returns an error. Both the standard UUID
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
@@ -68,7 +74,7 @@ func Parse(s string) (UUID, error) {
}
return uuid, nil
default:
- return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
+ return uuid, &invalidLengthError{len(s)}
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
@@ -112,7 +118,7 @@ func ParseBytes(b []byte) (UUID, error) {
}
return uuid, nil
default:
- return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
+ return uuid, &invalidLengthError{len(b)}
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9688f84e3..39771fbe8 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -163,7 +163,7 @@ github.com/containers/ocicrypt/keywrap/pgp
github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils
-# github.com/containers/psgo v1.5.1
+# github.com/containers/psgo v1.5.2
github.com/containers/psgo
github.com/containers/psgo/internal/capabilities
github.com/containers/psgo/internal/cgroups
@@ -318,7 +318,7 @@ github.com/golang/protobuf/ptypes/timestamp
github.com/google/gofuzz
# github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/google/shlex
-# github.com/google/uuid v1.1.2
+# github.com/google/uuid v1.1.3
github.com/google/uuid
# github.com/gorilla/mux v1.8.0
github.com/gorilla/mux