Make exec support --cidfile.

Fixes: #21256

Signed-off-by: Martin Glatzle <findessp@yandex.ru>
This commit is contained in:
Martin Glatzle
2024-07-06 00:33:04 +02:00
parent b762c15e1c
commit f1527283d6
3 changed files with 73 additions and 9 deletions

View File

@ -50,6 +50,7 @@ var (
envInput, envFile []string
execOpts entities.ExecOptions
execDetach bool
execCidFile string
)
func execFlags(cmd *cobra.Command) {
@ -63,6 +64,10 @@ func execFlags(cmd *cobra.Command) {
flags.StringVar(&execOpts.DetachKeys, detachKeysFlagName, containerConfig.DetachKeys(), "Select the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
_ = cmd.RegisterFlagCompletionFunc(detachKeysFlagName, common.AutocompleteDetachKeys)
cidfileFlagName := "cidfile"
flags.StringVar(&execCidFile, cidfileFlagName, "", "File to read the container ID from")
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
envFlagName := "env"
flags.StringArrayVarP(&envInput, envFlagName, "e", []string{}, "Set environment variables")
_ = cmd.RegisterFlagCompletionFunc(envFlagName, completion.AutocompleteNone)
@ -116,16 +121,12 @@ func init() {
}
func exec(cmd *cobra.Command, args []string) error {
var nameOrID string
nameOrID, command, err := determineTargetCtrAndCmd(args, execOpts.Latest, execCidFile != "")
if err != nil {
return err
}
execOpts.Cmd = command
if len(args) == 0 && !execOpts.Latest {
return errors.New("exec requires the name or ID of a container or the --latest flag")
}
execOpts.Cmd = args
if !execOpts.Latest {
execOpts.Cmd = args[1:]
nameOrID = strings.TrimPrefix(args[0], "/")
}
// Validate given environment variables
execOpts.Envs = make(map[string]string)
for _, f := range envFile {
@ -191,6 +192,33 @@ func exec(cmd *cobra.Command, args []string) error {
return nil
}
// determineTargetCtrAndCmd determines which command exec should run in which container
func determineTargetCtrAndCmd(args []string, latestSpecified bool, execCidFileProvided bool) (string, []string, error) {
var nameOrID string
var command []string
if len(args) == 0 && !latestSpecified && !execCidFileProvided {
return "", nil, errors.New("exec requires the name or ID of a container or the --latest or --cidfile flag")
} else if latestSpecified && execCidFileProvided {
return "", nil, errors.New("--latest and --cidfile can not be used together")
}
command = args
if !latestSpecified {
if !execCidFileProvided {
// assume first arg to be name or ID
command = args[1:]
nameOrID = strings.TrimPrefix(args[0], "/")
} else {
content, err := os.ReadFile(execCidFile)
if err != nil {
return "", nil, fmt.Errorf("reading CIDFile: %w", err)
}
nameOrID = strings.Split(string(content), "\n")[0]
}
}
return nameOrID, command, nil
}
func execWait(ctr string, seconds int32) error {
maxDuration := time.Duration(seconds) * time.Second
interval := 100 * time.Millisecond

View File

@ -13,6 +13,10 @@ podman\-exec - Execute a command in a running container
## OPTIONS
#### **--cidfile**=*file*
Read the ID of the target container from the specified *file*.
#### **--detach**, **-d**
Start the exec session, but do not attach to it. The command runs in the background, and the exec session is automatically removed when it completes. The **podman exec** command prints the ID of the exec session and exits immediately after it starts.

View File

@ -60,6 +60,38 @@ var _ = Describe("Podman exec", func() {
Expect(session).Should(ExitCleanly())
})
It("podman exec simple command using cidfile", func() {
cidFile := filepath.Join(tempdir, "cid")
session := podmanTest.RunTopContainerWithArgs("test1", []string{"--cidfile", cidFile})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
result := podmanTest.Podman([]string{"exec", "--cidfile", cidFile, "ls"})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
})
It("podman exec latest and cidfile", func() {
SkipIfRemote("--latest flag n/a")
cidFile := filepath.Join(tempdir, "cid")
session := podmanTest.RunTopContainerWithArgs("test1", []string{"--cidfile", cidFile})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
result := podmanTest.Podman([]string{"exec", "--cidfile", cidFile, "--latest", "ls"})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitWithError(125, `--latest and --cidfile can not be used together`))
})
It("podman exec nonextant cidfile", func() {
session := podmanTest.Podman([]string{"exec", "--cidfile", "foobar", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitWithError(125, `reading CIDFile: open foobar: no such file or directory`))
})
It("podman exec environment test", func() {
setup := podmanTest.RunTopContainer("test1")
setup.WaitWithDefaultTimeout()