summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--README.md2
-rw-r--r--cmd/podman/containers_prune.go4
-rw-r--r--cmd/podmanV2/containers/prune.go86
-rw-r--r--go.mod2
-rw-r--r--go.sum2
-rwxr-xr-xhack/swagger-check317
-rw-r--r--libpod/runtime_ctr.go3
-rw-r--r--pkg/api/handlers/compat/containers_prune.go13
-rw-r--r--pkg/api/server/register_containers.go12
-rw-r--r--pkg/api/server/register_images.go2
-rw-r--r--pkg/autoupdate/autoupdate.go25
-rw-r--r--pkg/bindings/containers/containers.go10
-rw-r--r--pkg/bindings/test/containers_test.go65
-rw-r--r--pkg/domain/entities/containers.go16
-rw-r--r--pkg/domain/entities/engine_container.go1
-rw-r--r--pkg/domain/infra/abi/containers.go17
-rw-r--r--pkg/domain/infra/tunnel/containers.go4
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go4
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf10
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go3
-rw-r--r--vendor/modules.txt2
22 files changed, 568 insertions, 38 deletions
diff --git a/Makefile b/Makefile
index 9121fae1f..e22d74f5d 100644
--- a/Makefile
+++ b/Makefile
@@ -397,6 +397,10 @@ install-podman-remote-%-docs: podman-remote docs $(MANPAGES)
man-page-check:
hack/man-page-checker
+.PHONY: swagger-check
+swagger-check:
+ hack/swagger-check
+
.PHONY: codespell
codespell:
codespell -S bin,vendor,.git,go.sum,changelog.txt,seccomp.json,.cirrus.yml,"*.xz,*.gz,*.tar,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist -w
@@ -624,7 +628,7 @@ validate.completions: completions/bash/podman
if [ -x /bin/zsh ]; then /bin/zsh completions/zsh/_podman; fi
.PHONY: validate
-validate: gofmt lint .gitvalidation validate.completions man-page-check
+validate: gofmt lint .gitvalidation validate.completions man-page-check swagger-check
.PHONY: build-all-new-commits
build-all-new-commits:
diff --git a/README.md b/README.md
index d5f682ee2..8cc010a45 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Libpod provides a library for applications looking to use the Container Pod concept,
popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`. Podman manages pods, containers, container images, and container volumes.
-* [Latest Version: 1.8.2](https://github.com/containers/libpod/releases/latest)
+* [Latest Version: 1.9.0](https://github.com/containers/libpod/releases/latest)
* [Continuous Integration:](contrib/cirrus/README.md) [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod/master)
* [GoDoc: ![GoDoc](https://godoc.org/github.com/containers/libpod/libpod?status.svg)](https://godoc.org/github.com/containers/libpod/libpod)
* Automated continuous release downloads (including remote-client):
diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go
index cd9817e7e..3953a489d 100644
--- a/cmd/podman/containers_prune.go
+++ b/cmd/podman/containers_prune.go
@@ -19,12 +19,12 @@ var (
pruneContainersDescription = `
podman container prune
- Removes all exited containers
+ Removes all stopped | exited containers
`
_pruneContainersCommand = &cobra.Command{
Use: "prune",
Args: noSubArgs,
- Short: "Remove all stopped containers",
+ Short: "Remove all stopped | exited containers",
Long: pruneContainersDescription,
RunE: func(cmd *cobra.Command, args []string) error {
pruneContainersCommand.InputArgs = args
diff --git a/cmd/podmanV2/containers/prune.go b/cmd/podmanV2/containers/prune.go
new file mode 100644
index 000000000..2d3af5d1d
--- /dev/null
+++ b/cmd/podmanV2/containers/prune.go
@@ -0,0 +1,86 @@
+package containers
+
+import (
+ "bufio"
+ "context"
+ "fmt"
+ "net/url"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ pruneDescription = fmt.Sprintf(`podman container prune
+
+ Removes all stopped | exited containers`)
+ pruneCommand = &cobra.Command{
+ Use: "prune [flags]",
+ Short: "Remove all stopped | exited containers",
+ Long: pruneDescription,
+ RunE: prune,
+ Example: `podman container prune`,
+ }
+ force bool
+ filter = []string{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: pruneCommand,
+ Parent: containerCmd,
+ })
+ flags := pruneCommand.Flags()
+ flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation. The default is false")
+ flags.StringArrayVar(&filter, "filter", []string{}, "Provide filter values (e.g. 'label=<key>=<value>')")
+}
+
+func prune(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ pruneOptions = entities.ContainerPruneOptions{}
+ )
+ if len(args) > 0 {
+ return errors.Errorf("`%s` takes no arguments", cmd.CommandPath())
+ }
+ if !force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Println("WARNING! This will remove all stopped containers.")
+ fmt.Print("Are you sure you want to continue? [y/N] ")
+ answer, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(answer)[0] != 'y' {
+ return nil
+ }
+ }
+
+ // TODO Remove once filter refactor is finished and url.Values done.
+ for _, f := range filter {
+ t := strings.SplitN(f, "=", 2)
+ pruneOptions.Filters = make(url.Values)
+ if len(t) < 2 {
+ return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
+ }
+ pruneOptions.Filters.Add(t[0], t[1])
+ }
+ responses, err := registry.ContainerEngine().ContainerPrune(context.Background(), pruneOptions)
+
+ if err != nil {
+ return err
+ }
+ for k := range responses.ID {
+ fmt.Println(k)
+ }
+ for _, v := range responses.Err {
+ errs = append(errs, v)
+ }
+ return errs.PrintErrors()
+}
diff --git a/go.mod b/go.mod
index 08e52e83b..bfc30b198 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921
github.com/containernetworking/plugins v0.8.5
github.com/containers/buildah v1.14.8
- github.com/containers/common v0.8.1
+ github.com/containers/common v0.9.0
github.com/containers/conmon v2.0.14+incompatible
github.com/containers/image/v5 v5.4.3
github.com/containers/psgo v1.4.0
diff --git a/go.sum b/go.sum
index 2ca41f042..9940f4119 100644
--- a/go.sum
+++ b/go.sum
@@ -67,6 +67,8 @@ github.com/containers/buildah v1.14.8 h1:JbMI0QSOmyZ30Mr2633uCXAj+Fajgh/EFS9xX/Y
github.com/containers/buildah v1.14.8/go.mod h1:ytEjHJQnRXC1ygXMyc0FqYkjcoCydqBQkOdxbH563QU=
github.com/containers/common v0.8.1 h1:1IUwAtZ4mC7GYRr4AC23cHf2oXCuoLzTUoSzIkSgnYw=
github.com/containers/common v0.8.1/go.mod h1:VxDJbaA1k6N1TNv9Rt6bQEF4hyKVHNfOfGA5L91ADEs=
+github.com/containers/common v0.9.0 h1:mN4P8VK6e7lqQSl7oywfEnhMtSzi8DhkE2QaJHJp88w=
+github.com/containers/common v0.9.0/go.mod h1:9YGKPwu6NFYQG2NtSP9bRhNGA8mgd1mUCCkOU2tr+Pc=
github.com/containers/conmon v2.0.14+incompatible h1:knU1O1QxXy5YxtjMQVKEyCajROaehizK9FHaICl+P5Y=
github.com/containers/conmon v2.0.14+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.4.3 h1:zn2HR7uu4hpvT5QQHgjqonOzKDuM1I1UHUEmzZT5sbs=
diff --git a/hack/swagger-check b/hack/swagger-check
new file mode 100755
index 000000000..d564b6554
--- /dev/null
+++ b/hack/swagger-check
@@ -0,0 +1,317 @@
+#!/usr/bin/perl
+#
+# swagger-check - Look for inconsistencies between swagger and source code
+#
+package LibPod::SwaggerCheck;
+
+use v5.14;
+use strict;
+use warnings;
+
+use File::Find;
+
+(our $ME = $0) =~ s|.*/||;
+(our $VERSION = '$Revision: 1.7 $ ') =~ tr/[0-9].//cd;
+
+# For debugging, show data structures using DumpTree($var)
+#use Data::TreeDumper; $Data::TreeDumper::Displayaddress = 0;
+
+###############################################################################
+# BEGIN user-customizable section
+
+our $Default_Dir = 'pkg/api/server';
+
+# END user-customizable section
+###############################################################################
+
+###############################################################################
+# BEGIN boilerplate args checking, usage messages
+
+sub usage {
+ print <<"END_USAGE";
+Usage: $ME [OPTIONS] DIRECTORY-TO-CHECK
+
+$ME scans all .go files under the given DIRECTORY-TO-CHECK
+(default: $Default_Dir), looking for lines of the form 'r.Handle(...)'
+or 'r.HandleFunc(...)'. For each such line, we check for a preceding
+swagger comment line and verify that the comment line matches the
+declarations in the r.Handle() invocation.
+
+For example, the following would be a correctly-matching pair of lines:
+
+ // swagger:operation GET /images/json compat getImages
+ r.Handle(VersionedPath("/images/json"), s.APIHandler(compat.GetImages)).Methods(http.MethodGet)
+
+...because http.MethodGet matches GET in the comment, the endpoint
+is /images/json in both cases, the APIHandler() says "compat" so
+that's the swagger tag, and the swagger operation name is the
+same as the APIHandler but with a lower-case first letter.
+
+The following is an inconsistency as reported by this script:
+
+pkg/api/server/register_info.go:
+- // swagger:operation GET /info libpod libpodGetInfo
++ // ................. ... ..... compat
+ r.Handle(VersionedPath("/info"), s.APIHandler(compat.GetInfo)).Methods(http.MethodGet)
+
+...because APIHandler() says 'compat' but the swagger comment
+says 'libpod'.
+
+OPTIONS:
+
+ --pedantic Compare operation names (the last part of swagger comment).
+ There are far too many of these inconsistencies to allow us
+ to enable this by default, but it still might be a useful
+ check in some circumstances.
+
+ -v, --verbose show verbose progress indicators
+ -n, --dry-run make no actual changes
+
+ --help display this message
+ --version display program name and version
+END_USAGE
+
+ exit;
+}
+
+# Command-line options. Note that this operates directly on @ARGV !
+our $pedantic;
+our $debug = 0;
+our $force = 0;
+our $verbose = 0;
+our $NOT = ''; # print "blahing the blah$NOT\n" if $debug
+sub handle_opts {
+ use Getopt::Long;
+ GetOptions(
+ 'pedantic' => \$pedantic,
+
+ 'debug!' => \$debug,
+ 'dry-run|n!' => sub { $NOT = ' [NOT]' },
+ 'force' => \$force,
+ 'verbose|v' => \$verbose,
+
+ help => \&usage,
+ man => \&man,
+ version => sub { print "$ME version $VERSION\n"; exit 0 },
+ ) or die "Try `$ME --help' for help\n";
+}
+
+# END boilerplate args checking, usage messages
+###############################################################################
+
+############################## CODE BEGINS HERE ###############################
+
+my $exit_status = 0;
+
+# The term is "modulino".
+__PACKAGE__->main() unless caller();
+
+# Main code.
+sub main {
+ # Note that we operate directly on @ARGV, not on function parameters.
+ # This is deliberate: it's because Getopt::Long only operates on @ARGV
+ # and there's no clean way to make it use @_.
+ handle_opts(); # will set package globals
+
+ # Fetch command-line arguments. Barf if too many.
+ my $dir = shift(@ARGV) || $Default_Dir;
+ die "$ME: Too many arguments; try $ME --help\n" if @ARGV;
+
+ # Find and act upon all matching files
+ find { wanted => sub { finder(@_) }, no_chdir => 1 }, $dir;
+
+ exit $exit_status;
+}
+
+
+############
+# finder # File::Find action - looks for 'r.Handle' or 'r.HandleFunc'
+############
+sub finder {
+ my $path = $File::Find::name;
+ return if $path =~ m|/\.|; # skip dotfiles
+ return unless $path =~ /\.go$/; # Only want .go files
+
+ print $path, "\n" if $debug;
+
+ # Read each .go file. Keep a running tally of all '// comment' lines;
+ # if we see a 'r.Handle()' or 'r.HandleFunc()' line, pass it + comments
+ # to analysis function.
+ open my $in, '<', $path
+ or die "$ME: Cannot read $path: $!\n";
+ my @comments;
+ while (my $line = <$in>) {
+ if ($line =~ m!^\s*//!) {
+ push @comments, $line;
+ }
+ else {
+ # Not a comment line. If it's an r.Handle*() one, process it.
+ if ($line =~ m!^\s*r\.Handle(Func)?\(!) {
+ handle_handle($path, $line, @comments)
+ or $exit_status = 1;
+ }
+
+ # Reset comments
+ @comments = ();
+ }
+ }
+ close $in;
+}
+
+
+###################
+# handle_handle # Cross-check a 'r.Handle*' declaration against swagger
+###################
+#
+# Returns false if swagger comment is inconsistent with function call,
+# true if it matches or if there simply isn't a swagger comment.
+#
+sub handle_handle {
+ my $path = shift; # for error messages only
+ my $line = shift; # in: the r.Handle* line
+ my @comments = @_; # in: preceding comment lines
+
+ # Preserve the original line, so we can show it in comments
+ my $line_orig = $line;
+
+ # Strip off the 'r.Handle*(' and leading whitespace; preserve the latter
+ $line =~ s!^(\s*)r\.Handle(Func)?\(!!
+ or die "$ME: INTERNAL ERROR! Got '$line'!\n";
+ my $indent = $1;
+
+ # Some have VersionedPath, some don't. Doesn't seem to make a difference
+ # in terms of swagger, so let's just ignore it.
+ $line =~ s!^VersionedPath\(([^\)]+)\)!$1!;
+ $line =~ m!^"(/[^"]+)",!
+ or die "$ME: $path:$.: Cannot grok '$line'\n";
+ my $endpoint = $1;
+
+ # FIXME: in older code, '{name:..*}' meant 'nameOrID'. As of 2020-02
+ # it looks like most of the '{name:..*}' entries are gone, except for one.
+###FIXME-obsolete? $endpoint =~ s|\{name:\.\.\*\}|{nameOrID}|;
+
+ # e.g. /auth, /containers/*/rename, /distribution, /monitor, /plugins
+ return 1 if $line =~ /\.UnsupportedHandler/;
+
+ #
+ # Determine the HTTP METHOD (GET, POST, DELETE, HEAD)
+ #
+ my $method;
+ if ($line =~ /generic.VersionHandler/) {
+ $method = 'GET';
+ }
+ elsif ($line =~ m!\.Methods\((.*)\)!) {
+ my $x = $1;
+
+ if ($x =~ /Method(Post|Get|Delete|Head)/) {
+ $method = uc $1;
+ }
+ elsif ($x =~ /\"(HEAD|GET|POST)"/) {
+ $method = $1;
+ }
+ else {
+ die "$ME: $path:$.: Cannot grok $x\n";
+ }
+ }
+ else {
+ warn "$ME: $path:$.: No Methods in '$line'\n";
+ return 1;
+ }
+
+ #
+ # Determine the SWAGGER TAG. Assume 'compat' unless we see libpod; but
+ # this can be overruled (see special case below)
+ #
+ my $tag = ($endpoint =~ /(libpod)/ ? $1 : 'compat');
+
+ #
+ # Determine the OPERATION. *** NOTE: This is mostly useless! ***
+ # In an ideal world the swagger comment would match actual function call;
+ # in reality there are over thirty mismatches. Use --pedantic to see.
+ #
+ my $operation = '';
+ if ($line =~ /(generic|handlers|compat)\.(\w+)/) {
+ $operation = lcfirst $2;
+ if ($endpoint =~ m!/libpod/! && $operation !~ /^libpod/) {
+ $operation = 'libpod' . ucfirst $operation;
+ }
+ }
+ elsif ($line =~ /(libpod)\.(\w+)/) {
+ $operation = "$1$2";
+ }
+
+ # Special case: the following endpoints all get a custom tag
+ if ($endpoint =~ m!/(volumes|pods|manifests)/!) {
+ $tag = $1;
+ $operation =~ s/^libpod//;
+ $operation = lcfirst $operation;
+ }
+
+ # Special case: anything related to 'events' gets a system tag
+ if ($endpoint =~ m!/events!) {
+ $tag = 'system';
+ }
+
+ # Special case: /changes is libpod even though it says compat
+ if ($endpoint =~ m!/changes!) {
+ $tag = 'libpod';
+ }
+
+ state $previous_path; # Previous path name, to avoid dups
+
+ #
+ # Compare actual swagger comment to what we expect based on Handle call.
+ #
+ my $expect = " // swagger:operation $method $endpoint $tag $operation ";
+ my @actual = grep { /swagger:operation/ } @comments;
+
+ return 1 if !@actual; # No swagger comment in file; oh well
+
+ my $actual = $actual[0];
+
+ # By default, don't compare the operation: there are far too many
+ # mismatches here.
+ if (! $pedantic) {
+ $actual =~ s/\s+\S+\s*$//;
+ $expect =~ s/\s+\S+\s*$//;
+ }
+
+ # (Ignore whitespace discrepancies)
+ (my $a_trimmed = $actual) =~ s/\s+/ /g;
+
+ return 1 if $a_trimmed eq $expect;
+
+ # Mismatch. Display it. Start with filename, if different from previous
+ print "\n";
+ if (!$previous_path || $previous_path ne $path) {
+ print $path, ":\n";
+ }
+ $previous_path = $path;
+
+ # Show the actual line, prefixed with '-' ...
+ print "- $actual[0]";
+ # ...then our generated ones, but use '...' as a way to ignore matches
+ print "+ $indent//";
+ my @actual_split = split ' ', $actual;
+ my @expect_split = split ' ', $expect;
+ for my $i (1 .. $#actual_split) {
+ print " ";
+ if ($actual_split[$i] eq ($expect_split[$i]||'')) {
+ print "." x length($actual_split[$i]);
+ }
+ else {
+ # Show the difference. Use terminal highlights if available.
+ print "\e[1;37m" if -t *STDOUT;
+ print $expect_split[$i];
+ print "\e[m" if -t *STDOUT;
+ }
+ }
+ print "\n";
+
+ # Show the r.Handle* code line itself
+ print " ", $line_orig;
+
+ return;
+}
+
+1;
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 207ac6477..9d3e69d56 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -887,8 +887,9 @@ func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int
continue
}
err = r.RemoveContainer(context.Background(), ctr, false, false)
- pruneErrors[ctr.ID()] = err
if err != nil {
+ pruneErrors[ctr.ID()] = err
+ } else {
prunedContainers[ctr.ID()] = size
}
}
diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go
index a56c3903d..bf3aecd65 100644
--- a/pkg/api/handlers/compat/containers_prune.go
+++ b/pkg/api/handlers/compat/containers_prune.go
@@ -4,8 +4,8 @@ import (
"net/http"
"github.com/containers/libpod/libpod"
- "github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
"github.com/docker/docker/api/types"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@@ -40,14 +40,11 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) {
// Libpod response differs
if utils.IsLibpodRequest(r) {
- var response []handlers.LibpodContainersPruneReport
- for ctrID, size := range prunedContainers {
- response = append(response, handlers.LibpodContainersPruneReport{ID: ctrID, SpaceReclaimed: size})
+ report := &entities.ContainerPruneReport{
+ Err: pruneErrors,
+ ID: prunedContainers,
}
- for ctrID, err := range pruneErrors {
- response = append(response, handlers.LibpodContainersPruneReport{ID: ctrID, PruneError: err.Error()})
- }
- utils.WriteResponse(w, http.StatusOK, response)
+ utils.WriteResponse(w, http.StatusOK, report)
return
}
for ctrID, size := range prunedContainers {
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 8b9a9e312..378d1e06c 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -955,7 +955,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// "$ref": "#/responses/NoSuchContainer"
// 500:
// "$ref": "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/pause"), s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/pause"), s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost)
// swagger:operation POST /libpod/containers/{name}/restart libpod libpodRestartContainer
// ---
// tags:
@@ -1282,7 +1282,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name}/export"), s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
- // swagger:operation GET /libpod/containers/{name}/checkout libpod libpodCheckpointContainer
+ // swagger:operation POST /libpod/containers/{name}/checkpoint libpod libpodCheckpointContainer
// ---
// tags:
// - containers
@@ -1323,7 +1323,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name}/checkpoint"), s.APIHandler(libpod.Checkpoint)).Methods(http.MethodPost)
- // swagger:operation GET /libpod/containers/{name} restore libpod libpodRestoreContainer
+ // swagger:operation POST /libpod/containers/{name}/restore libpod libpodRestoreContainer
// ---
// tags:
// - containers
@@ -1407,9 +1407,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/changes"), s.APIHandler(compat.Changes))
- r.HandleFunc("/containers/{name}/changes", s.APIHandler(compat.Changes))
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/changes"), s.APIHandler(compat.Changes))
+ r.HandleFunc(VersionedPath("/containers/{name}/changes"), s.APIHandler(compat.Changes)).Methods(http.MethodGet)
+ r.HandleFunc("/containers/{name}/changes", s.APIHandler(compat.Changes)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/changes"), s.APIHandler(compat.Changes)).Methods(http.MethodGet)
// swagger:operation POST /libpod/containers/{name}/init libpod libpodInitContainer
// ---
// tags:
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 7dd887037..6cc6f0cfa 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -1154,7 +1154,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/images/{name}/changes"), s.APIHandler(compat.Changes))
+ r.HandleFunc(VersionedPath("/libpod/images/{name}/changes"), s.APIHandler(compat.Changes)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go
index 7c243eb00..78d5ac474 100644
--- a/pkg/autoupdate/autoupdate.go
+++ b/pkg/autoupdate/autoupdate.go
@@ -201,18 +201,25 @@ func imageContainersMap(runtime *libpod.Runtime) (map[string][]*libpod.Container
if state != define.ContainerStateRunning {
continue
}
+
// Only update containers with the specific label/policy set.
labels := ctr.Labels()
- if value, exists := labels[Label]; exists {
- policy, err := LookupPolicy(value)
- if err != nil {
- errors = append(errors, err)
- continue
- }
- if policy != PolicyNewImage {
- continue
- }
+ value, exists := labels[Label]
+ if !exists {
+ continue
}
+
+ policy, err := LookupPolicy(value)
+ if err != nil {
+ errors = append(errors, err)
+ continue
+ }
+
+ // Skip non-image labels (could be explicitly disabled).
+ if policy != PolicyNewImage {
+ continue
+ }
+
// Now we know that `ctr` is configured for auto updates.
id, _ := ctr.Image()
imageMap[id] = append(imageMap[id], allContainers[i])
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index 963f0ec57..e74a256c7 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -60,10 +60,8 @@ func List(ctx context.Context, filters map[string][]string, all *bool, last *int
// 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, filters map[string][]string) ([]string, error) {
- var (
- pruneResponse []string
- )
+func Prune(ctx context.Context, filters map[string][]string) (*entities.ContainerPruneReport, error) {
+ var reports *entities.ContainerPruneReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
@@ -78,9 +76,9 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/prune", params)
if err != nil {
- return pruneResponse, err
+ return nil, err
}
- return pruneResponse, response.Process(pruneResponse)
+ return reports, response.Process(&reports)
}
// Remove removes a container from local storage. The force bool designates
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 0b1b9ecdd..e288dc368 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -531,4 +531,69 @@ var _ = Describe("Podman containers ", func() {
Expect(err).ToNot(BeNil())
})
+ It("podman prune stoped containers", func() {
+ // Start and stop a container to enter in exited state.
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ err = containers.Stop(bt.conn, name, nil)
+ Expect(err).To(BeNil())
+
+ // 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))
+ })
+
+ It("podman prune stoped containers with filters", func() {
+ // Start and stop a container to enter in exited state.
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ err = containers.Stop(bt.conn, name, nil)
+ Expect(err).To(BeNil())
+
+ // Invalid filter keys should return error.
+ filtersIncorrect := map[string][]string{
+ "status": {"dummy"},
+ }
+ pruneResponse, err := containers.Prune(bt.conn, filtersIncorrect)
+ Expect(err).ToNot(BeNil())
+
+ // Mismatched filter params no container should be pruned.
+ filtersIncorrect = map[string][]string{
+ "name": {"r"},
+ }
+ pruneResponse, err = containers.Prune(bt.conn, filtersIncorrect)
+ Expect(err).To(BeNil())
+ Expect(len(pruneResponse.Err)).To(Equal(0))
+ Expect(len(pruneResponse.ID)).To(Equal(0))
+
+ // Valid filter params container should be pruned now.
+ filters := map[string][]string{
+ "name": {"top"},
+ }
+ pruneResponse, err = containers.Prune(bt.conn, filters)
+ Expect(err).To(BeNil())
+ Expect(len(pruneResponse.Err)).To(Equal(0))
+ Expect(len(pruneResponse.ID)).To(Equal(1))
+ })
+
+ It("podman prune running containers", func() {
+ // Start the container.
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+
+ // Check if the container is running.
+ data, err := containers.Inspect(bt.conn, name, nil)
+ Expect(err).To(BeNil())
+ Expect(data.State.Status).To(Equal("running"))
+
+ // 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))
+ })
})
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index f21af9ce4..52327a905 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -2,6 +2,7 @@ package entities
import (
"io"
+ "net/url"
"os"
"time"
@@ -260,7 +261,7 @@ type ContainerRunOptions struct {
}
// ContainerRunReport describes the results of running
-//a container
+// a container
type ContainerRunReport struct {
ExitCode int
Id string
@@ -327,3 +328,16 @@ type ContainerUnmountReport struct {
Err error
Id string
}
+
+// ContainerPruneOptions describes the options needed
+// to prune a container from the CLI
+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
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 5fdb9a8a6..c3092a98a 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -13,6 +13,7 @@ type ContainerEngine interface {
ContainerAttach(ctx context.Context, nameOrId string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error)
+ ContainerPrune(ctx context.Context, options ContainerPruneOptions) (*ContainerPruneReport, error)
ContainerCommit(ctx context.Context, nameOrId string, options CommitOptions) (*CommitReport, error)
ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error)
ContainerDiff(ctx context.Context, nameOrId string, options DiffOptions) (*DiffReport, error)
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index f464df3ac..fc62a6c29 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -19,6 +19,7 @@ import (
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/libpod/logs"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/checkpoint"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi/terminal"
@@ -173,6 +174,22 @@ 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) {
+ filterFuncs, err := utils.GenerateFilterFuncsFromMap(ic.Libpod, options.Filters)
+ if err != nil {
+ return nil, err
+ }
+ prunedContainers, pruneErrors, err := ic.Libpod.PruneContainers(filterFuncs)
+ if err != nil {
+ return nil, err
+ }
+ report := entities.ContainerPruneReport{
+ ID: prunedContainers,
+ Err: pruneErrors,
+ }
+ return &report, nil
+}
+
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
var (
reports []*entities.KillReport
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 05b62efcf..679bb371b 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -146,6 +146,10 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
return reports, nil
}
+func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) {
+ return containers.Prune(ic.ClientCxt, options.Filters)
+}
+
func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) {
var (
reports []*entities.ContainerInspectReport
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index b65db2722..ef21f1d9f 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -271,6 +271,10 @@ type EngineConfig struct {
// running containers without CGroups.
RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroupv2"`
+ // RuntimeSupportsKVM is a list of OCI runtimes that support
+ // KVM separation for conatainers.
+ RuntimeSupportsKVM []string `toml:"runtime_supports_kvm"`
+
// SetOptions contains a subset of config options. It's used to indicate if
// a given option has either been set by the user or by the parsed
// configuration file. If not, the corresponding option might be
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index 067be429e..fbc691f1d 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -347,6 +347,14 @@
#
# runtime_supports_json = ["crun", "runc", "kata"]
+# List of the OCI runtimes that supports running containers without cgroups.
+#
+# runtime_supports_nocgroups = ["crun"]
+
+# List of the OCI runtimes that supports running containers with KVM Separation.
+#
+# runtime_supports_kvm = ["kata"]
+
# Paths to look for a valid OCI runtime (runc, runv, kata, etc)
[engine.runtimes]
# runc = [
@@ -376,6 +384,8 @@
# "/usr/local/sbin/kata-runtime",
# "/sbin/kata-runtime",
# "/bin/kata-runtime",
+# "/usr/bin/kata-qemu",
+# "/usr/bin/kata-fc",
# ]
# Number of seconds to wait for container to exit before sending kill signal.
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 78bfd8a28..5f3af1f8d 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -246,6 +246,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
"/usr/local/sbin/kata-runtime",
"/sbin/kata-runtime",
"/bin/kata-runtime",
+ "/usr/bin/kata-qemu",
+ "/usr/bin/kata-fc",
},
}
c.ConmonEnvVars = []string{
@@ -267,6 +269,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
"runc",
}
c.RuntimeSupportsNoCgroups = []string{"crun"}
+ c.RuntimeSupportsKVM = []string{"kata", "kata-runtime", "kata-qemu", "kata-fc"}
c.InitPath = DefaultInitPath
c.NoPivotRoot = false
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 535090e81..9aa167530 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -82,7 +82,7 @@ github.com/containers/buildah/pkg/secrets
github.com/containers/buildah/pkg/supplemented
github.com/containers/buildah/pkg/umask
github.com/containers/buildah/util
-# github.com/containers/common v0.8.1
+# github.com/containers/common v0.9.0
github.com/containers/common/pkg/apparmor
github.com/containers/common/pkg/capabilities
github.com/containers/common/pkg/cgroupv2