diff options
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" } |
