add --cidfile to container kill

Add the ability to read container ids from one or more files for the
kill command.

Fixes: #8443

Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
baude
2020-12-23 11:02:52 -06:00
parent 54b82a175f
commit c81e29525b
6 changed files with 90 additions and 5 deletions

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v2/cmd/podman/common" "github.com/containers/podman/v2/cmd/podman/common"
"github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/cmd/podman/utils"
@ -22,7 +23,7 @@ var (
Long: killDescription, Long: killDescription,
RunE: kill, RunE: kill,
Args: func(cmd *cobra.Command, args []string) error { Args: func(cmd *cobra.Command, args []string) error {
return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) return validate.CheckAllLatestAndCIDFile(cmd, args, false, true)
}, },
ValidArgsFunction: common.AutocompleteContainersRunning, ValidArgsFunction: common.AutocompleteContainersRunning,
Example: `podman kill mywebserver Example: `podman kill mywebserver
@ -32,7 +33,7 @@ var (
containerKillCommand = &cobra.Command{ containerKillCommand = &cobra.Command{
Args: func(cmd *cobra.Command, args []string) error { Args: func(cmd *cobra.Command, args []string) error {
return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) return validate.CheckAllLatestAndCIDFile(cmd, args, false, true)
}, },
Use: killCommand.Use, Use: killCommand.Use,
Short: killCommand.Short, Short: killCommand.Short,
@ -57,6 +58,9 @@ func killFlags(cmd *cobra.Command) {
signalFlagName := "signal" signalFlagName := "signal"
flags.StringVarP(&killOptions.Signal, signalFlagName, "s", "KILL", "Signal to send to the container") flags.StringVarP(&killOptions.Signal, signalFlagName, "s", "KILL", "Signal to send to the container")
_ = cmd.RegisterFlagCompletionFunc(signalFlagName, common.AutocompleteStopSignal) _ = cmd.RegisterFlagCompletionFunc(signalFlagName, common.AutocompleteStopSignal)
cidfileFlagName := "cidfile"
flags.StringArrayVar(&killOptions.CIDFiles, cidfileFlagName, []string{}, "Read the container ID from the file")
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
} }
func init() { func init() {

View File

@ -16,6 +16,10 @@ The main process inside each container specified will be sent SIGKILL, or any si
Signal all running containers. This does not include paused containers. Signal all running containers. This does not include paused containers.
#### **--cidfile**
Read container ID from the specified file and remove the container. Can be specified multiple times.
#### **--latest**, **-l** #### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
@ -40,6 +44,10 @@ podman kill --latest
podman kill --signal KILL -a podman kill --signal KILL -a
podman kill --cidfile /home/user/cidfile-1
podman kill --cidfile /home/user/cidfile-1 --cidfile ./cidfile-2
## SEE ALSO ## SEE ALSO
podman(1), podman-stop(1) podman(1), podman-stop(1)

View File

@ -107,6 +107,7 @@ type KillOptions struct {
All bool All bool
Latest bool Latest bool
Signal string Signal string
CIDFiles []string
} }
type KillReport struct { type KillReport struct {

View File

@ -229,6 +229,14 @@ func (ic *ContainerEngine) pruneContainersHelper(filterFuncs []libpod.ContainerF
} }
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) { func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
for _, cidFile := range options.CIDFiles {
content, err := ioutil.ReadFile(cidFile)
if err != nil {
return nil, errors.Wrap(err, "error reading CIDFile")
}
id := strings.Split(string(content), "\n")[0]
namesOrIds = append(namesOrIds, id)
}
sig, err := signal.ParseSignalNameOrNumber(options.Signal) sig, err := signal.ParseSignalNameOrNumber(options.Signal)
if err != nil { if err != nil {
return nil, err return nil, err
@ -246,6 +254,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
} }
return reports, nil return reports, nil
} }
func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) { func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) {
var ( var (
ctrs []*libpod.Container ctrs []*libpod.Container

View File

@ -125,6 +125,14 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
} }
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, opts entities.KillOptions) ([]*entities.KillReport, error) { func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, opts entities.KillOptions) ([]*entities.KillReport, error) {
for _, cidFile := range opts.CIDFiles {
content, err := ioutil.ReadFile(cidFile)
if err != nil {
return nil, errors.Wrap(err, "error reading CIDFile")
}
id := strings.Split(string(content), "\n")[0]
namesOrIds = append(namesOrIds, id)
}
ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, false, namesOrIds) ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, false, namesOrIds)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -1,6 +1,7 @@
package integration package integration
import ( import (
"io/ioutil"
"os" "os"
. "github.com/containers/podman/v2/test/utils" . "github.com/containers/podman/v2/test/utils"
@ -112,4 +113,58 @@ var _ = Describe("Podman kill", func() {
Expect(result.ExitCode()).To(Equal(0)) Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
}) })
It("podman kill --cidfile", func() {
tmpDir, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
tmpFile := tmpDir + "cid"
defer os.RemoveAll(tmpDir)
session := podmanTest.Podman([]string{"run", "-dt", "--cidfile", tmpFile, ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
cid := session.OutputToStringArray()[0]
kill := podmanTest.Podman([]string{"kill", "--cidfile", tmpFile})
kill.WaitWithDefaultTimeout()
Expect(kill.ExitCode()).To(BeZero())
wait := podmanTest.Podman([]string{"wait", "--condition", "exited", cid})
wait.WaitWithDefaultTimeout()
Expect(wait.ExitCode()).To(BeZero())
})
It("podman kill multiple --cidfile", func() {
tmpDir1, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
tmpFile1 := tmpDir1 + "cid"
defer os.RemoveAll(tmpDir1)
tmpDir2, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
tmpFile2 := tmpDir2 + "cid"
defer os.RemoveAll(tmpDir2)
session := podmanTest.Podman([]string{"run", "-dt", "--cidfile", tmpFile1, ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
cid1 := session.OutputToStringArray()[0]
session2 := podmanTest.Podman([]string{"run", "-dt", "--cidfile", tmpFile2, ALPINE, "top"})
session2.WaitWithDefaultTimeout()
Expect(session2.ExitCode()).To(Equal(0))
cid2 := session2.OutputToStringArray()[0]
kill := podmanTest.Podman([]string{"kill", "--cidfile", tmpFile1, "--cidfile", tmpFile2})
kill.WaitWithDefaultTimeout()
Expect(kill.ExitCode()).To(BeZero())
wait := podmanTest.Podman([]string{"wait", "--condition", "exited", cid1})
wait.WaitWithDefaultTimeout()
Expect(wait.ExitCode()).To(BeZero())
wait = podmanTest.Podman([]string{"wait", "--condition", "exited", cid2})
wait.WaitWithDefaultTimeout()
Expect(wait.ExitCode()).To(BeZero())
})
}) })