aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/containers/kill.go7
-rw-r--r--cmd/podman/containers/rm.go24
-rw-r--r--cmd/podman/containers/stop.go7
-rw-r--r--cmd/podman/kube/down.go39
-rw-r--r--cmd/podman/kube/play.go67
-rwxr-xr-xcontrib/cirrus/setup_environment.sh4
-rw-r--r--docs/source/markdown/podman-kube-down.1.md43
-rw-r--r--docs/source/markdown/podman-kube-play.1.md12
-rw-r--r--docs/source/markdown/podman-kube.1.md5
-rw-r--r--docs/source/markdown/podman-rm.1.md24
-rwxr-xr-xhack/swagger-check4
-rw-r--r--libpod/runtime_ctr.go4
-rw-r--r--pkg/api/handlers/swagger/responses.go2
-rw-r--r--pkg/api/server/register_play.go (renamed from pkg/api/server/register_kube.go)14
-rw-r--r--pkg/api/server/server.go2
-rw-r--r--pkg/bindings/kube/kube.go4
-rw-r--r--pkg/domain/entities/containers.go1
-rw-r--r--pkg/domain/entities/reports/containers.go5
-rw-r--r--pkg/domain/infra/abi/containers.go43
-rw-r--r--pkg/domain/infra/tunnel/containers.go57
-rw-r--r--pkg/domain/infra/tunnel/helpers.go2
-rw-r--r--pkg/systemd/generate/containers.go3
-rw-r--r--pkg/systemd/generate/containers_test.go50
-rw-r--r--test/e2e/mount_rootless_test.go22
-rw-r--r--test/e2e/rm_test.go65
-rw-r--r--test/system/055-rm.bats1
-rw-r--r--test/system/200-pod.bats1
-rw-r--r--test/system/700-play.bats15
-rw-r--r--test/upgrade/test-upgrade.bats4
29 files changed, 417 insertions, 114 deletions
diff --git a/cmd/podman/containers/kill.go b/cmd/podman/containers/kill.go
index 5a5379389..c08b3abb6 100644
--- a/cmd/podman/containers/kill.go
+++ b/cmd/podman/containers/kill.go
@@ -49,7 +49,8 @@ var (
)
var (
- killOptions = entities.KillOptions{}
+ killOptions = entities.KillOptions{}
+ killCidFiles = []string{}
)
func killFlags(cmd *cobra.Command) {
@@ -61,7 +62,7 @@ func killFlags(cmd *cobra.Command) {
flags.StringVarP(&killOptions.Signal, signalFlagName, "s", "KILL", "Signal to send to the container")
_ = cmd.RegisterFlagCompletionFunc(signalFlagName, common.AutocompleteStopSignal)
cidfileFlagName := "cidfile"
- flags.StringArrayVar(&cidFiles, cidfileFlagName, []string{}, "Read the container ID from the file")
+ flags.StringArrayVar(&killCidFiles, cidfileFlagName, nil, "Read the container ID from the file")
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
}
@@ -94,7 +95,7 @@ func kill(_ *cobra.Command, args []string) error {
if sig < 1 || sig > 64 {
return errors.New("valid signals are 1 through 64")
}
- for _, cidFile := range cidFiles {
+ for _, cidFile := range killCidFiles {
content, err := ioutil.ReadFile(cidFile)
if err != nil {
return fmt.Errorf("error reading CIDFile: %w", err)
diff --git a/cmd/podman/containers/rm.go b/cmd/podman/containers/rm.go
index 056e32651..1e3976389 100644
--- a/cmd/podman/containers/rm.go
+++ b/cmd/podman/containers/rm.go
@@ -52,8 +52,10 @@ var (
)
var (
- rmOptions = entities.RmOptions{}
- cidFiles = []string{}
+ rmOptions = entities.RmOptions{
+ Filters: make(map[string][]string),
+ }
+ rmCidFiles = []string{}
)
func rmFlags(cmd *cobra.Command) {
@@ -69,9 +71,13 @@ func rmFlags(cmd *cobra.Command) {
flags.BoolVarP(&rmOptions.Volumes, "volumes", "v", false, "Remove anonymous volumes associated with the container")
cidfileFlagName := "cidfile"
- flags.StringArrayVar(&cidFiles, cidfileFlagName, nil, "Read the container ID from the file")
+ flags.StringArrayVar(&rmCidFiles, cidfileFlagName, nil, "Read the container ID from the file")
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
+ filterFlagName := "filter"
+ flags.StringSliceVar(&filters, filterFlagName, []string{}, "Filter output based on conditions given")
+ _ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePsFilters)
+
if !registry.IsRemote() {
// This option is deprecated, but needs to still exists for backwards compatibility
flags.Bool("storage", false, "Remove container from storage library")
@@ -101,7 +107,7 @@ func rm(cmd *cobra.Command, args []string) error {
}
rmOptions.Timeout = &stopTimeout
}
- for _, cidFile := range cidFiles {
+ for _, cidFile := range rmCidFiles {
content, err := ioutil.ReadFile(cidFile)
if err != nil {
return fmt.Errorf("error reading CIDFile: %w", err)
@@ -110,6 +116,14 @@ func rm(cmd *cobra.Command, args []string) error {
args = append(args, id)
}
+ for _, f := range filters {
+ split := strings.SplitN(f, "=", 2)
+ if len(split) < 2 {
+ return fmt.Errorf("invalid filter %q", f)
+ }
+ rmOptions.Filters[split[0]] = append(rmOptions.Filters[split[0]], split[1])
+ }
+
if rmOptions.All {
logrus.Debug("--all is set: enforcing --depend=true")
rmOptions.Depend = true
@@ -147,7 +161,7 @@ func removeContainers(namesOrIDs []string, rmOptions entities.RmOptions, setExit
}
errs = append(errs, r.Err)
} else {
- fmt.Println(r.Id)
+ fmt.Println(r.RawInput)
}
}
return errs.PrintErrors()
diff --git a/cmd/podman/containers/stop.go b/cmd/podman/containers/stop.go
index 261f441c3..b0f449266 100644
--- a/cmd/podman/containers/stop.go
+++ b/cmd/podman/containers/stop.go
@@ -52,7 +52,8 @@ var (
stopOptions = entities.StopOptions{
Filters: make(map[string][]string),
}
- stopTimeout uint
+ stopCidFiles = []string{}
+ stopTimeout uint
)
func stopFlags(cmd *cobra.Command) {
@@ -62,7 +63,7 @@ func stopFlags(cmd *cobra.Command) {
flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing")
cidfileFlagName := "cidfile"
- flags.StringArrayVar(&cidFiles, cidfileFlagName, nil, "Read the container ID from the file")
+ flags.StringArrayVar(&stopCidFiles, cidfileFlagName, nil, "Read the container ID from the file")
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
timeFlagName := "time"
@@ -103,7 +104,7 @@ func stop(cmd *cobra.Command, args []string) error {
if cmd.Flag("time").Changed {
stopOptions.Timeout = &stopTimeout
}
- for _, cidFile := range cidFiles {
+ for _, cidFile := range stopCidFiles {
content, err := ioutil.ReadFile(cidFile)
if err != nil {
return fmt.Errorf("error reading CIDFile: %w", err)
diff --git a/cmd/podman/kube/down.go b/cmd/podman/kube/down.go
new file mode 100644
index 000000000..b8c025928
--- /dev/null
+++ b/cmd/podman/kube/down.go
@@ -0,0 +1,39 @@
+package pods
+
+import (
+ "github.com/containers/podman/v4/cmd/podman/common"
+ "github.com/containers/podman/v4/cmd/podman/registry"
+ "github.com/spf13/cobra"
+)
+
+var (
+ downDescription = `Reads in a structured file of Kubernetes YAML.
+
+ Removes pods that have been based on the Kubernetes kind described in the YAML.`
+
+ downCmd = &cobra.Command{
+ Use: "down KUBEFILE|-",
+ Short: "Remove pods based on Kubernetes YAML.",
+ Long: downDescription,
+ RunE: down,
+ Args: cobra.ExactArgs(1),
+ ValidArgsFunction: common.AutocompleteDefaultOneArg,
+ Example: `podman kube down nginx.yml
+ cat nginx.yml | podman kube down -`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Command: downCmd,
+ Parent: kubeCmd,
+ })
+}
+
+func down(cmd *cobra.Command, args []string) error {
+ reader, err := readerFromArg(args[0])
+ if err != nil {
+ return err
+ }
+ return teardown(reader)
+}
diff --git a/cmd/podman/kube/play.go b/cmd/podman/kube/play.go
index 685cb521c..4811bcf4b 100644
--- a/cmd/podman/kube/play.go
+++ b/cmd/podman/kube/play.go
@@ -1,8 +1,10 @@
package pods
import (
+ "bytes"
"errors"
"fmt"
+ "io"
"net"
"os"
"strings"
@@ -37,9 +39,9 @@ var (
// https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
defaultSeccompRoot = "/var/lib/kubelet/seccomp"
playOptions = playKubeOptionsWrapper{}
- playDescription = `Command reads in a structured file of Kubernetes YAML.
+ playDescription = `Reads in a structured file of Kubernetes YAML.
- It creates pods or volumes based on the Kubernetes kind described in the YAML. Supported kinds are Pods, Deployments and PersistentVolumeClaims.`
+ Creates pods or volumes based on the Kubernetes kind described in the YAML. Supported kinds are Pods, Deployments and PersistentVolumeClaims.`
playCmd = &cobra.Command{
Use: "play [options] KUBEFILE|-",
@@ -139,6 +141,7 @@ func playFlags(cmd *cobra.Command) {
downFlagName := "down"
flags.BoolVar(&playOptions.Down, downFlagName, false, "Stop pods defined in the YAML file")
+ _ = flags.MarkHidden("down")
replaceFlagName := "replace"
flags.BoolVar(&playOptions.Replace, replaceFlagName, false, "Delete and recreate pods defined in the YAML file")
@@ -223,10 +226,6 @@ func Play(cmd *cobra.Command, args []string) error {
}
playOptions.Annotations[splitN[0]] = annotation
}
- yamlfile := args[0]
- if yamlfile == "-" {
- yamlfile = "/dev/stdin"
- }
for _, mac := range playOptions.macs {
m, err := net.ParseMAC(mac)
@@ -235,36 +234,62 @@ func Play(cmd *cobra.Command, args []string) error {
}
playOptions.StaticMACs = append(playOptions.StaticMACs, m)
}
+
+ reader, err := readerFromArg(args[0])
+ if err != nil {
+ return err
+ }
+
if playOptions.Down {
- return teardown(yamlfile)
+ return teardown(reader)
}
+
if playOptions.Replace {
- if err := teardown(yamlfile); err != nil && !errorhandling.Contains(err, define.ErrNoSuchPod) {
+ if err := teardown(reader); err != nil && !errorhandling.Contains(err, define.ErrNoSuchPod) {
+ return err
+ }
+ if _, err := reader.Seek(0, 0); err != nil {
return err
}
}
- return kubeplay(yamlfile)
+ return kubeplay(reader)
}
func playKube(cmd *cobra.Command, args []string) error {
return Play(cmd, args)
}
-func teardown(yamlfile string) error {
+func readerFromArg(fileName string) (*bytes.Reader, error) {
+ if fileName == "-" { // Read from stdin
+ data, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ return nil, err
+ }
+ return bytes.NewReader(data), nil
+ }
+ f, err := os.Open(fileName)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ data, err := io.ReadAll(f)
+ if err != nil {
+ return nil, err
+ }
+ return bytes.NewReader(data), nil
+}
+
+func teardown(body io.Reader) error {
var (
podStopErrors utils.OutputErrors
podRmErrors utils.OutputErrors
)
options := new(entities.PlayKubeDownOptions)
- f, err := os.Open(yamlfile)
+ reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), body, *options)
if err != nil {
return err
}
- defer f.Close()
- reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), f, *options)
- if err != nil {
- return fmt.Errorf("%v: %w", yamlfile, err)
- }
// Output stopped pods
fmt.Println("Pods stopped:")
@@ -290,19 +315,15 @@ func teardown(yamlfile string) error {
podRmErrors = append(podRmErrors, removed.Err)
}
}
+
return podRmErrors.PrintErrors()
}
-func kubeplay(yamlfile string) error {
- f, err := os.Open(yamlfile)
+func kubeplay(body io.Reader) error {
+ report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), body, playOptions.PlayKubeOptions)
if err != nil {
return err
}
- defer f.Close()
- report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), f, playOptions.PlayKubeOptions)
- if err != nil {
- return fmt.Errorf("%s: %w", yamlfile, err)
- }
// Print volumes report
for i, volume := range report.Volumes {
if i == 0 {
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index c3b7811bc..f84f78ee9 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -277,7 +277,7 @@ case "$TEST_FLAVOR" in
;& # continue with next item
compose)
make install.tools
- rpm -ivh $PACKAGE_DOWNLOAD_DIR/podman-docker*
+ dnf install -y $PACKAGE_DOWNLOAD_DIR/podman-docker*
;& # continue with next item
int) ;&
sys) ;&
@@ -307,7 +307,7 @@ case "$TEST_FLAVOR" in
install_test_configs
;;
machine)
- rpm -ivh $PACKAGE_DOWNLOAD_DIR/podman-gvproxy*
+ dnf install -y $PACKAGE_DOWNLOAD_DIR/podman-gvproxy*
remove_packaged_podman_files
make install.tools
make install PREFIX=/usr ETCDIR=/etc
diff --git a/docs/source/markdown/podman-kube-down.1.md b/docs/source/markdown/podman-kube-down.1.md
new file mode 100644
index 000000000..35725043b
--- /dev/null
+++ b/docs/source/markdown/podman-kube-down.1.md
@@ -0,0 +1,43 @@
+% podman-kube-down(1)
+
+## NAME
+podman-kube-down - Remove containers and pods based on Kubernetes YAML
+
+## SYNOPSIS
+**podman kube down** *file.yml|-*
+
+## DESCRIPTION
+**podman kube down** reads a specified Kubernetes YAML file, tearing down pods that were created by the `podman kube play` command via the same Kubernetes YAML file. Any volumes that were created by the previous `podman kube play` command remain intact. If the YAML file is specified as `-`, `podman kube down` reads the YAML from stdin.
+
+## EXAMPLES
+
+Example YAML file `demo.yml`:
+```
+apiVersion: v1
+kind: Pod
+metadata:
+...
+spec:
+ containers:
+ - command:
+ - top
+ - name: container
+ value: podman
+ image: foobar
+...
+```
+
+Remove the pod and containers as described in the `demo.yml` file
+```
+$ podman kube down demo.yml
+52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
+```
+
+Remove the pod and containers as described in the`demo.yml` file YAML sent to stdin
+```
+$ cat demo.yml | podman kube play -
+52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
+```
+
+## SEE ALSO
+**[podman(1)](podman.1.md)**, **[podman-kube(1)](podman-kube.1.md)**, **[podman-kube-play(1)](podman-kube-play.1.md)**, **[podman-generate-kube(1)](podman-generate-kube.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**
diff --git a/docs/source/markdown/podman-kube-play.1.md b/docs/source/markdown/podman-kube-play.1.md
index 25248ce99..b3c385fe9 100644
--- a/docs/source/markdown/podman-kube-play.1.md
+++ b/docs/source/markdown/podman-kube-play.1.md
@@ -1,7 +1,7 @@
% podman-kube-play(1)
## NAME
-podman-kube-play - Create containers, pods or volumes based on Kubernetes YAML
+podman-kube-play - Create containers, pods and volumes based on Kubernetes YAML
## SYNOPSIS
**podman kube play** [*options*] *file.yml|-*
@@ -30,6 +30,9 @@ Note: If the `:latest` tag is used, Podman will attempt to pull the image from a
Note: The command `podman play kube` is an alias of `podman kube play`, and will perform the same function.
+Note: The command `podman kube down` can be used to stop and remove pods or containers based on the same Kubernetes YAML used
+by `podman kube play` to create them.
+
`Kubernetes PersistentVolumeClaims`
A Kubernetes PersistentVolumeClaim represents a Podman named volume. Only the PersistentVolumeClaim name is required by Podman to create a volume. Kubernetes annotations can be used to make use of the available options for Podman volumes.
@@ -145,11 +148,6 @@ The [username[:password]] to use to authenticate with the registry if required.
If one or both values are not supplied, a command line prompt will appear and the
value can be entered. The password is entered without echo.
-#### **--down**
-
-Tears down the pods that were created by a previous run of `kube play`. The pods are stopped and then
-removed. Any volumes created are left intact.
-
#### **--help**, **-h**
Print usage statement
@@ -325,7 +323,7 @@ $ podman kube play demo.yml --network net1:ip=10.89.1.5 --network net2:ip=10.89.
Please take into account that networks must be created first using podman-network-create(1).
## SEE ALSO
-**[podman(1)](podman.1.md)**, **[podman-kube(1)](podman-kube.1.md)**, **[podman-network-create(1)](podman-network-create.1.md)**, **[podman-generate-kube(1)](podman-generate-kube.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**
+**[podman(1)](podman.1.md)**, **[podman-kube(1)](podman-kube.1.md)**, **[podman-kube-down(1)](podman-kube-down.1.md)**, **[podman-network-create(1)](podman-network-create.1.md)**, **[podman-generate-kube(1)](podman-generate-kube.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**
## HISTORY
December 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
diff --git a/docs/source/markdown/podman-kube.1.md b/docs/source/markdown/podman-kube.1.md
index f815ffae2..7a6978a2b 100644
--- a/docs/source/markdown/podman-kube.1.md
+++ b/docs/source/markdown/podman-kube.1.md
@@ -14,7 +14,8 @@ file input. Containers will be automatically started.
| Command | Man Page | Description |
| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
-| play | [podman-kube-play(1)](podman-kube-play.1.md) | Create containers, pods or volumes based on Kubernetes YAML. |
+| down | [podman-kube-down(1)](podman-kube-down.1.md) | Remove containers and pods based on Kubernetes YAML. |
+| play | [podman-kube-play(1)](podman-kube-play.1.md) | Create containers, pods and volumes based on Kubernetes YAML. |
## SEE ALSO
-**[podman(1)](podman.1.md)**, **[podman-pod(1)](podman-pod.1.md)**, **[podman-container(1)](podman-container.1.md)**, **[podman-generate(1)](podman-generate.1.md)**, **[podman-kube-play(1)](podman-kube-play.1.md)**
+**[podman(1)](podman.1.md)**, **[podman-pod(1)](podman-pod.1.md)**, **[podman-container(1)](podman-container.1.md)**, **[podman-generate(1)](podman-generate.1.md)**, **[podman-kube-play(1)](podman-kube-play.1.md)**, **[podman-kube-down(1)](podman-kube-down.1.md)**
diff --git a/docs/source/markdown/podman-rm.1.md b/docs/source/markdown/podman-rm.1.md
index 1fac3aa34..1dbd1d0c3 100644
--- a/docs/source/markdown/podman-rm.1.md
+++ b/docs/source/markdown/podman-rm.1.md
@@ -26,6 +26,30 @@ Read container ID from the specified file and remove the container. Can be spec
Remove selected container and recursively remove all containers that depend on it.
+#### **--filter**=*filter*
+
+Filter what containers remove.
+Multiple filters can be given with multiple uses of the --filter flag.
+Filters with the same key work inclusive with the only exception being
+`label` which is exclusive. Filters with different keys always work exclusive.
+
+Valid filters are listed below:
+
+| **Filter** | **Description** |
+| --------------- | -------------------------------------------------------------------------------- |
+| id | [ID] Container's ID (accepts regex) |
+| name | [Name] Container's name (accepts regex) |
+| label | [Key] or [Key=Value] Label assigned to a container |
+| exited | [Int] Container's exit code |
+| status | [Status] Container's status: 'created', 'exited', 'paused', 'running', 'unknown' |
+| ancestor | [ImageName] Image or descendant used to create container |
+| before | [ID] or [Name] Containers created before this container |
+| since | [ID] or [Name] Containers created since this container |
+| volume | [VolumeName] or [MountpointDestination] Volume mounted in container |
+| health | [Status] healthy or unhealthy |
+| pod | [Pod] name or full or partial ID of pod |
+| network | [Network] name or full ID of network |
+
#### **--force**, **-f**
Force the removal of running and paused containers. Forcing a container removal also
diff --git a/hack/swagger-check b/hack/swagger-check
index 1e5b95c3a..b4481f5bb 100755
--- a/hack/swagger-check
+++ b/hack/swagger-check
@@ -320,8 +320,8 @@ sub operation_name {
if ($action eq 'df') {
$action = 'dataUsage';
}
- elsif ($action eq "delete" && $endpoint eq "/libpod/kube/play") {
- $action = "PlayDown"
+ elsif ($action eq "delete" && $endpoint eq "/libpod/play/kube") {
+ $action = "KubeDown"
}
# Grrrrrr, this one is annoying: some operations get an extra 'All'
elsif ($action =~ /^(delete|get|stats)$/ && $endpoint !~ /\{/) {
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index ce0fd869d..703ae5cbe 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -995,7 +995,7 @@ func (r *Runtime) RemoveDepend(ctx context.Context, rmCtr *Container, force bool
return nil, err
}
for _, cID := range podContainerIDS {
- rmReports = append(rmReports, &reports.RmReport{Id: cID})
+ rmReports = append(rmReports, &reports.RmReport{Id: cID, RawInput: cID})
}
return rmReports, nil
}
@@ -1023,7 +1023,7 @@ func (r *Runtime) RemoveDepend(ctx context.Context, rmCtr *Container, force bool
rmReports = append(rmReports, reports...)
}
- report := reports.RmReport{Id: rmCtr.ID()}
+ report := reports.RmReport{Id: rmCtr.ID(), RawInput: rmCtr.ID()}
report.Err = r.removeContainer(ctx, rmCtr, force, removeVolume, false, timeout)
return append(rmReports, &report), nil
}
diff --git a/pkg/api/handlers/swagger/responses.go b/pkg/api/handlers/swagger/responses.go
index 5731f8edd..93a508b39 100644
--- a/pkg/api/handlers/swagger/responses.go
+++ b/pkg/api/handlers/swagger/responses.go
@@ -71,7 +71,7 @@ type imagesRemoveResponseLibpod struct {
// PlayKube response
// swagger:response
-type kubePlayResponseLibpod struct {
+type playKubeResponseLibpod struct {
// in:body
Body entities.PlayKubeReport
}
diff --git a/pkg/api/server/register_kube.go b/pkg/api/server/register_play.go
index 6ae9e8123..76e150504 100644
--- a/pkg/api/server/register_kube.go
+++ b/pkg/api/server/register_play.go
@@ -7,8 +7,8 @@ import (
"github.com/gorilla/mux"
)
-func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
- // swagger:operation POST /libpod/kube/play libpod KubePlayLibpod
+func (s *APIServer) registerPlayHandlers(r *mux.Router) error {
+ // swagger:operation POST /libpod/play/kube libpod PlayKubeLibpod
// ---
// tags:
// - containers
@@ -57,12 +57,12 @@ func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
// - application/json
// responses:
// 200:
- // $ref: "#/responses/kubePlayResponseLibpod"
+ // $ref: "#/responses/playKubeResponseLibpod"
// 500:
// $ref: "#/responses/internalError"
- r.HandleFunc(VersionedPath("/libpod/kube/play"), s.APIHandler(libpod.KubePlay)).Methods(http.MethodPost)
r.HandleFunc(VersionedPath("/libpod/play/kube"), s.APIHandler(libpod.PlayKube)).Methods(http.MethodPost)
- // swagger:operation DELETE /libpod/kube/play libpod KubePlayDownLibpod
+ r.HandleFunc(VersionedPath("/libpod/kube/play"), s.APIHandler(libpod.KubePlay)).Methods(http.MethodPost)
+ // swagger:operation DELETE /libpod/play/kube libpod PlayKubeDownLibpod
// ---
// tags:
// - containers
@@ -73,10 +73,10 @@ func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
// - application/json
// responses:
// 200:
- // $ref: "#/responses/kubePlayResponseLibpod"
+ // $ref: "#/responses/playKubeResponseLibpod"
// 500:
// $ref: "#/responses/internalError"
- r.HandleFunc(VersionedPath("/libpod/kube/play"), s.APIHandler(libpod.KubePlayDown)).Methods(http.MethodDelete)
r.HandleFunc(VersionedPath("/libpod/play/kube"), s.APIHandler(libpod.PlayKubeDown)).Methods(http.MethodDelete)
+ r.HandleFunc(VersionedPath("/libpod/kube/play"), s.APIHandler(libpod.KubePlayDown)).Methods(http.MethodDelete)
return nil
}
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index a6d8b5e4c..5482a8ec2 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -126,11 +126,11 @@ func newServer(runtime *libpod.Runtime, listener net.Listener, opts entities.Ser
server.registerHealthCheckHandlers,
server.registerImagesHandlers,
server.registerInfoHandlers,
- server.registerKubeHandlers,
server.registerManifestHandlers,
server.registerMonitorHandlers,
server.registerNetworkHandlers,
server.registerPingHandlers,
+ server.registerPlayHandlers,
server.registerPluginsHandlers,
server.registerPodsHandlers,
server.registerSecretHandlers,
diff --git a/pkg/bindings/kube/kube.go b/pkg/bindings/kube/kube.go
index b9cc0efa7..db40c5134 100644
--- a/pkg/bindings/kube/kube.go
+++ b/pkg/bindings/kube/kube.go
@@ -51,7 +51,7 @@ func PlayWithBody(ctx context.Context, body io.Reader, options *PlayOptions) (*e
return nil, err
}
- response, err := conn.DoRequest(ctx, body, http.MethodPost, "/kube/play", params, header)
+ response, err := conn.DoRequest(ctx, body, http.MethodPost, "/play/kube", params, header)
if err != nil {
return nil, err
}
@@ -85,7 +85,7 @@ func DownWithBody(ctx context.Context, body io.Reader) (*entities.KubePlayReport
return nil, err
}
- response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/kube/play", nil, nil)
+ response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", nil, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index df793034b..7048cd1d2 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -131,6 +131,7 @@ type RestartReport struct {
}
type RmOptions struct {
+ Filters map[string][]string
All bool
Depend bool
Force bool
diff --git a/pkg/domain/entities/reports/containers.go b/pkg/domain/entities/reports/containers.go
index db9a66012..6759fc402 100644
--- a/pkg/domain/entities/reports/containers.go
+++ b/pkg/domain/entities/reports/containers.go
@@ -1,8 +1,9 @@
package reports
type RmReport struct {
- Id string `json:"Id"` //nolint:revive,stylecheck
- Err error `json:"Err,omitempty"`
+ Id string `json:"Id"` //nolint:revive,stylecheck
+ Err error `json:"Err,omitempty"`
+ RawInput string
}
func RmReportsIds(r []*RmReport) []string {
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 783224e9c..ed149a869 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -142,10 +142,10 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
if err != nil {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
if len(rawInputs) == len(ctrs) {
for i := range ctrs {
- ctrMap[ctrs[i].ID()] = rawInputs[i]
+ idToRawInput[ctrs[i].ID()] = rawInputs[i]
}
}
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
@@ -158,7 +158,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
reports = append(reports, &entities.PauseUnpauseReport{
Id: c.ID(),
Err: err,
- RawInput: ctrMap[c.ID()],
+ RawInput: idToRawInput[c.ID()],
})
}
return reports, nil
@@ -169,10 +169,10 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
if err != nil {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
if len(rawInputs) == len(ctrs) {
for i := range ctrs {
- ctrMap[ctrs[i].ID()] = rawInputs[i]
+ idToRawInput[ctrs[i].ID()] = rawInputs[i]
}
}
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
@@ -185,7 +185,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
reports = append(reports, &entities.PauseUnpauseReport{
Id: c.ID(),
Err: err,
- RawInput: ctrMap[c.ID()],
+ RawInput: idToRawInput[c.ID()],
})
}
return reports, nil
@@ -196,10 +196,10 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
if len(rawInputs) == len(ctrs) {
for i := range ctrs {
- ctrMap[ctrs[i].ID()] = rawInputs[i]
+ idToRawInput[ctrs[i].ID()] = rawInputs[i]
}
}
errMap, err := parallelctr.ContainerOp(ctx, ctrs, func(c *libpod.Container) error {
@@ -245,7 +245,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
if options.All {
report.RawInput = ctr.ID()
} else {
- report.RawInput = ctrMap[ctr.ID()]
+ report.RawInput = idToRawInput[ctr.ID()]
}
report.Err = err
reports = append(reports, report)
@@ -275,10 +275,10 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
if err != nil {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
if len(rawInputs) == len(ctrs) {
for i := range ctrs {
- ctrMap[ctrs[i].ID()] = rawInputs[i]
+ idToRawInput[ctrs[i].ID()] = rawInputs[i]
}
}
reports := make([]*entities.KillReport, 0, len(ctrs))
@@ -291,7 +291,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
reports = append(reports, &entities.KillReport{
Id: con.ID(),
Err: err,
- RawInput: ctrMap[con.ID()],
+ RawInput: idToRawInput[con.ID()],
})
}
return reports, nil
@@ -360,7 +360,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
// this will fail and code will fall through to removing the container from libpod.`
tmpNames := []string{}
for _, ctr := range names {
- report := reports.RmReport{Id: ctr}
+ report := reports.RmReport{Id: ctr, RawInput: ctr}
report.Err = ic.Libpod.RemoveStorageContainer(ctr, options.Force)
//nolint:gocritic
if report.Err == nil {
@@ -381,7 +381,16 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
}
names = tmpNames
- ctrs, err := getContainersByContext(options.All, options.Latest, names, ic.Libpod)
+ ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, names, options.Filters, ic.Libpod)
+ if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) {
+ return nil, err
+ }
+ idToRawInput := map[string]string{}
+ if len(rawInputs) == len(ctrs) {
+ for i := range ctrs {
+ idToRawInput[ctrs[i].ID()] = rawInputs[i]
+ }
+ }
if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) {
// Failed to get containers. If force is specified, get the containers ID
// and evict them
@@ -391,7 +400,10 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
for _, ctr := range names {
logrus.Debugf("Evicting container %q", ctr)
- report := reports.RmReport{Id: ctr}
+ report := reports.RmReport{
+ Id: ctr,
+ RawInput: idToRawInput[ctr],
+ }
_, err := ic.Libpod.EvictContainer(ctx, ctr, options.Volumes)
if err != nil {
if options.Ignore && errors.Is(err, define.ErrNoSuchCtr) {
@@ -461,6 +473,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
report := new(reports.RmReport)
report.Id = ctr.ID()
report.Err = err
+ report.RawInput = idToRawInput[ctr.ID()]
rmReports = append(rmReports, report)
}
return rmReports, nil
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 98c73c51a..225aee017 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -61,9 +61,9 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
if err != nil {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
for i := range ctrs {
- ctrMap[ctrs[i].ID] = rawInputs[i]
+ idToRawInput[ctrs[i].ID] = rawInputs[i]
}
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
@@ -75,7 +75,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
reports = append(reports, &entities.PauseUnpauseReport{
Id: c.ID,
Err: err,
- RawInput: ctrMap[c.ID],
+ RawInput: idToRawInput[c.ID],
})
}
return reports, nil
@@ -86,9 +86,9 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
if err != nil {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
for i := range ctrs {
- ctrMap[ctrs[i].ID] = rawInputs[i]
+ idToRawInput[ctrs[i].ID] = rawInputs[i]
}
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
@@ -100,7 +100,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
reports = append(reports, &entities.PauseUnpauseReport{
Id: c.ID,
Err: err,
- RawInput: ctrMap[c.ID],
+ RawInput: idToRawInput[c.ID],
})
}
return reports, nil
@@ -111,9 +111,9 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
if err != nil {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
for i := range ctrs {
- ctrMap[ctrs[i].ID] = rawInputs[i]
+ idToRawInput[ctrs[i].ID] = rawInputs[i]
}
options := new(containers.StopOptions).WithIgnore(opts.Ignore)
if to := opts.Timeout; to != nil {
@@ -123,7 +123,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
for _, c := range ctrs {
report := entities.StopReport{
Id: c.ID,
- RawInput: ctrMap[c.ID],
+ RawInput: idToRawInput[c.ID],
}
if err = containers.Stop(ic.ClientCtx, c.ID, options); err != nil {
// These first two are considered non-fatal under the right conditions
@@ -154,9 +154,9 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
if err != nil {
return nil, err
}
- ctrMap := map[string]string{}
+ idToRawInput := map[string]string{}
for i := range ctrs {
- ctrMap[ctrs[i].ID] = rawInputs[i]
+ idToRawInput[ctrs[i].ID] = rawInputs[i]
}
options := new(containers.KillOptions).WithSignal(opts.Signal)
reports := make([]*entities.KillReport, 0, len(ctrs))
@@ -169,7 +169,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
reports = append(reports, &entities.KillReport{
Id: c.ID,
Err: err,
- RawInput: ctrMap[c.ID],
+ RawInput: idToRawInput[c.ID],
})
}
return reports, nil
@@ -208,11 +208,18 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
toRemove := []string{}
alreadyRemoved := make(map[string]bool) // Avoids trying to remove already removed containers
- if opts.All {
- ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, opts.Ignore, nil)
+ idToRawInput := map[string]string{}
+
+ if opts.All || len(opts.Filters) > 0 {
+ ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, opts.All, opts.Ignore, nil, opts.Filters)
if err != nil {
return nil, err
}
+ if len(rawInputs) == len(ctrs) {
+ for i := range ctrs {
+ idToRawInput[ctrs[i].ID] = rawInputs[i]
+ }
+ }
for _, c := range ctrs {
toRemove = append(toRemove, c.ID)
}
@@ -225,10 +232,15 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
// instead of the ID. Since this can only happen
// with external containers, it poses no threat
// to the `alreadyRemoved` checks below.
- ctrs, err := getContainersByContext(ic.ClientCtx, false, true, []string{ctr})
+ ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, false, true, []string{ctr}, opts.Filters)
if err != nil {
return nil, err
}
+ if len(rawInputs) == len(ctrs) {
+ for i := range ctrs {
+ idToRawInput[ctrs[i].ID] = rawInputs[i]
+ }
+ }
id := ctr
if len(ctrs) == 1 {
id = ctrs[0].ID
@@ -238,13 +250,20 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
}
rmReports := make([]*reports.RmReport, 0, len(toRemove))
- for _, nameOrID := range toRemove {
- if alreadyRemoved[nameOrID] {
+ for _, rmCtr := range toRemove {
+ if alreadyRemoved[rmCtr] {
continue
}
- newReports, err := containers.Remove(ic.ClientCtx, nameOrID, options)
+ if ctr, exist := idToRawInput[rmCtr]; exist {
+ rmCtr = ctr
+ }
+ newReports, err := containers.Remove(ic.ClientCtx, rmCtr, options)
if err != nil {
- rmReports = append(rmReports, &reports.RmReport{Id: nameOrID, Err: err})
+ rmReports = append(rmReports, &reports.RmReport{
+ Id: rmCtr,
+ Err: err,
+ RawInput: idToRawInput[rmCtr],
+ })
continue
}
for i := range newReports {
diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go
index 9ff1641f0..a0b01dd71 100644
--- a/pkg/domain/infra/tunnel/helpers.go
+++ b/pkg/domain/infra/tunnel/helpers.go
@@ -14,7 +14,7 @@ import (
// FIXME: the `ignore` parameter is very likely wrong here as it should rather
// be used on *errors* from operations such as remove.
-func getContainersByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, error) {
+func getContainersByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, error) { //nolint:unparam
ctrs, _, err := getContainersAndInputByContext(contextWithConnection, all, ignore, namesOrIDs, nil)
return ctrs, err
}
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index 66905202d..1f8c519b7 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -378,6 +378,9 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst
fs.StringArrayP("env", "e", nil, "")
fs.String("sdnotify", "", "")
fs.String("restart", "", "")
+ // have to define extra -h flag to prevent help error when parsing -h hostname
+ // https://github.com/containers/podman/issues/15124
+ fs.StringP("help", "h", "", "")
if err := fs.Parse(remainingCmd); err != nil {
return "", fmt.Errorf("parsing remaining command-line arguments: %w", err)
}
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index 9a9e03a58..873cbfbb3 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -815,6 +815,37 @@ NotifyAccess=all
WantedBy=default.target
`
+ goodNewWithHostname := `# jadda-jadda.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman jadda-jadda.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=70
+ExecStartPre=/bin/rm -f %t/%n.ctr-id
+ExecStart=/usr/bin/podman run \
+ --cidfile=%t/%n.ctr-id \
+ --cgroups=no-conmon \
+ --rm \
+ --sdnotify=conmon \
+ -d \
+ -h hostname awesome-image:latest
+ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
+ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
+Type=notify
+NotifyAccess=all
+
+[Install]
+WantedBy=default.target
+`
+
templateGood := `# container-foo@.service
# autogenerated by Podman CI
@@ -1432,6 +1463,25 @@ WantedBy=default.target
false,
false,
},
+ {"good with -h hostname",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "jadda-jadda",
+ ContainerNameOrID: "jadda-jadda",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ CreateCommand: []string{"I'll get stripped", "create", "-h", "hostname", "awesome-image:latest"},
+ EnvVariable: define.EnvVariable,
+ },
+ goodNewWithHostname,
+ true,
+ false,
+ false,
+ false,
+ },
{"good template",
containerInfo{
Executable: "/usr/bin/podman",
diff --git a/test/e2e/mount_rootless_test.go b/test/e2e/mount_rootless_test.go
index 994a5899b..b0452deda 100644
--- a/test/e2e/mount_rootless_test.go
+++ b/test/e2e/mount_rootless_test.go
@@ -52,9 +52,16 @@ var _ = Describe("Podman mount", func() {
Expect(setup).Should(Exit(0))
cid := setup.OutputToString()
- session := podmanTest.Podman([]string{"unshare", PODMAN_BINARY, "mount", cid})
+ // command: podman <options> unshare podman <options> mount cid
+ args := []string{"unshare", podmanTest.PodmanBinary}
+ opts := podmanTest.PodmanMakeOptions([]string{"mount", cid}, false, false)
+ args = append(args, opts...)
+
+ // container root file system location is /tmp/... because "--root /tmp/..."
+ session := podmanTest.Podman(args)
session.WaitWithDefaultTimeout()
- Expect(setup).Should(Exit(0))
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/tmp"))
})
It("podman image mount", func() {
@@ -71,8 +78,15 @@ var _ = Describe("Podman mount", func() {
setup.WaitWithDefaultTimeout()
Expect(setup).Should(Exit(0))
- session := podmanTest.Podman([]string{"unshare", PODMAN_BINARY, "image", "mount", ALPINE})
+ // command: podman <options> unshare podman <options> image mount ALPINE
+ args := []string{"unshare", podmanTest.PodmanBinary}
+ opts := podmanTest.PodmanMakeOptions([]string{"image", "mount", ALPINE}, false, false)
+ args = append(args, opts...)
+
+ // image location is /tmp/... because "--root /tmp/..."
+ session := podmanTest.Podman(args)
session.WaitWithDefaultTimeout()
- Expect(setup).Should(Exit(0))
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/tmp"))
})
})
diff --git a/test/e2e/rm_test.go b/test/e2e/rm_test.go
index 7dbe5fed8..e76451824 100644
--- a/test/e2e/rm_test.go
+++ b/test/e2e/rm_test.go
@@ -1,6 +1,7 @@
package integration
import (
+ "fmt"
"io/ioutil"
"os"
@@ -51,6 +52,7 @@ var _ = Describe("Podman rm", func() {
result := podmanTest.Podman([]string{"rm", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(2))
+ Expect(result.ErrorToString()).To(ContainSubstring("containers cannot be removed without force"))
})
It("podman rm created container", func() {
@@ -140,11 +142,9 @@ var _ = Describe("Podman rm", func() {
output := result.OutputToString()
Expect(output).To(ContainSubstring(cid))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
-
})
It("podman rm --cidfile", func() {
-
tmpDir, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
tmpFile := tmpDir + "cid"
@@ -166,7 +166,6 @@ var _ = Describe("Podman rm", func() {
})
It("podman rm multiple --cidfile", func() {
-
tmpDir, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
tmpFile1 := tmpDir + "cid-1"
@@ -201,18 +200,22 @@ var _ = Describe("Podman rm", func() {
result := podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all", "--latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
result = podmanTest.Podman([]string{"rm", "--latest", "--all"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all and --latest cannot be used together"))
})
It("podman rm --all", func() {
@@ -242,10 +245,17 @@ var _ = Describe("Podman rm", func() {
session = podmanTest.Podman([]string{"rm", "bogus", cid})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
+ if IsRemote() {
+ Expect(session.OutputToString()).To(BeEquivalentTo(cid))
+ }
session = podmanTest.Podman([]string{"rm", "--ignore", "bogus", cid})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ if !IsRemote() {
+ Expect(session.OutputToString()).To(BeEquivalentTo(cid))
+ }
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
})
@@ -253,6 +263,7 @@ var _ = Describe("Podman rm", func() {
session := podmanTest.Podman([]string{"rm", "bogus"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
})
It("podman rm bogus container and a running container", func() {
@@ -263,10 +274,12 @@ var _ = Describe("Podman rm", func() {
session = podmanTest.Podman([]string{"rm", "bogus", "test1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
session = podmanTest.Podman([]string{"rm", "test1", "bogus"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
})
It("podman rm --ignore bogus container and a running container", func() {
@@ -274,12 +287,52 @@ var _ = Describe("Podman rm", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"rm", "-t", "0", "--force", "--ignore", "bogus", "test1"})
+ session = podmanTest.Podman([]string{"rm", "--ignore", "test1", "bogus"})
session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
+ Expect(session).Should(Exit(2))
+ Expect(session.ErrorToString()).To(ContainSubstring("containers cannot be removed without force"))
- session = podmanTest.Podman([]string{"rm", "--ignore", "test1", "bogus"})
+ session = podmanTest.Podman([]string{"rm", "-t", "0", "--force", "--ignore", "bogus", "test1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(BeEquivalentTo("test1"))
+ })
+
+ It("podman rm --filter", func() {
+ session1 := podmanTest.RunTopContainer("test1")
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid1 := session1.OutputToString()
+
+ session1 = podmanTest.RunTopContainer("test2")
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid2 := session1.OutputToString()
+
+ session1 = podmanTest.RunTopContainer("test3")
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid3 := session1.OutputToString()
+ shortCid3 := cid3[0:5]
+
+ session1 = podmanTest.Podman([]string{"rm", cid1, "-f", "--filter", "status=running"})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(125))
+ Expect(session1.ErrorToString()).To(ContainSubstring("--filter takes no arguments"))
+
+ session1 = podmanTest.Podman([]string{"rm", "-a", "-f", "--filter", fmt.Sprintf("id=%swrongid", shortCid3)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(HaveLen(0))
+
+ session1 = podmanTest.Podman([]string{"rm", "-a", "-f", "--filter", fmt.Sprintf("id=%s", shortCid3)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(BeEquivalentTo(cid3))
+
+ session1 = podmanTest.Podman([]string{"rm", "-f", "--filter", fmt.Sprintf("id=%s", cid2)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(BeEquivalentTo(cid2))
})
})
diff --git a/test/system/055-rm.bats b/test/system/055-rm.bats
index dcd679a1f..613c60c96 100644
--- a/test/system/055-rm.bats
+++ b/test/system/055-rm.bats
@@ -18,6 +18,7 @@ load helpers
# Remove container; now 'inspect' should fail
run_podman rm $rand
+ is "$output" "$rand" "display raw input"
run_podman 125 inspect $rand
}
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index cbbd62ffb..b1b9ee5e1 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -482,6 +482,7 @@ spec:
skip_if_remote "resource limits only implemented on non-remote"
skip_if_rootless "resource limits only work with root"
skip_if_cgroupsv1 "resource limits only meaningful on cgroups V2"
+ skip_if_aarch64 "FIXME: #15074 - flakes often on aarch64"
# create loopback device
lofile=${PODMAN_TMPDIR}/disk.img
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index 72602a9e6..e1955cfd1 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -182,8 +182,11 @@ EOF
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
is "$output" "none" "network mode none is set for the container"
- run_podman stop -a -t 0
- run_podman pod rm -t 0 -f test_pod
+ run_podman kube down - < $PODMAN_TMPDIR/test.yaml
+ run_podman 125 inspect test_pod-test
+ is "$output" ".*Error: inspecting object: no such object: \"test_pod-test\""
+ run_podman pod rm -a
+ run_podman rm -a
}
@test "podman play with user from image" {
@@ -325,7 +328,6 @@ spec:
- name: TERM
value: xterm
- name: container
-
value: podman
image: quay.io/libpod/userimage
name: test
@@ -353,6 +355,9 @@ status: {}
run_podman inspect --format "{{.HostConfig.LogConfig.Type}}" test_pod-test
is "$output" "$default_driver" "play kube uses default log driver"
- run_podman stop -a -t 0
- run_podman pod rm -t 0 -f test_pod
+ run_podman kube down $PODMAN_TMPDIR/test.yaml
+ run_podman 125 inspect test_pod-test
+ is "$output" ".*Error: inspecting object: no such object: \"test_pod-test\""
+ run_podman pod rm -a
+ run_podman rm -a
}
diff --git a/test/upgrade/test-upgrade.bats b/test/upgrade/test-upgrade.bats
index 5efe05d49..dca97e324 100644
--- a/test/upgrade/test-upgrade.bats
+++ b/test/upgrade/test-upgrade.bats
@@ -345,10 +345,10 @@ failed | exited | 17
@test "rm a stopped container" {
run_podman rm myfailedcontainer
- is "$output" "[0-9a-f]\\{64\\}" "podman rm myfailedcontainer"
+ is "$output" "myfailedcontainer" "podman rm myfailedcontainer"
run_podman rm mydonecontainer
- is "$output" "[0-9a-f]\\{64\\}" "podman rm mydonecontainer"
+ is "$output" "mydonecontainer" "podman rm mydonecontainer"
}