mirror of
https://github.com/containers/podman.git
synced 2025-07-03 17:27:18 +08:00
cmd/podman: add --latest option to update #26380
Allow users to target the most recently created container with `podman update --latest` (short `-l`). The same option already exists on many other commands, so this brings update in line with the rest of the CLI and saves users from typing or looking up the newest container. Fixes: #26380 Signed-off-by: Hayato Kihara <kai.21banana@gmail.com>
This commit is contained in:
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/containers/podman/v5/cmd/podman/common"
|
||||
"github.com/containers/podman/v5/cmd/podman/registry"
|
||||
"github.com/containers/podman/v5/cmd/podman/validate"
|
||||
"github.com/containers/podman/v5/libpod/define"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
"github.com/containers/podman/v5/pkg/specgen"
|
||||
@ -24,7 +25,7 @@ var (
|
||||
Short: "Update an existing container",
|
||||
Long: updateDescription,
|
||||
RunE: update,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Args: validate.IDOrLatestArgs,
|
||||
ValidArgsFunction: common.AutocompleteContainers,
|
||||
Example: `podman update --cpus=5 foobar_container`,
|
||||
}
|
||||
@ -39,13 +40,17 @@ var (
|
||||
Example: `podman container update --cpus=5 foobar_container`,
|
||||
}
|
||||
)
|
||||
var (
|
||||
updateOpts entities.ContainerCreateOptions
|
||||
)
|
||||
|
||||
type ContainerUpdateOptions struct {
|
||||
entities.ContainerCreateOptions
|
||||
Latest bool
|
||||
}
|
||||
|
||||
var updateOptions ContainerUpdateOptions
|
||||
|
||||
func updateFlags(cmd *cobra.Command) {
|
||||
common.DefineCreateDefaults(&updateOpts)
|
||||
common.DefineCreateFlags(cmd, &updateOpts, entities.UpdateMode)
|
||||
common.DefineCreateDefaults(&updateOptions.ContainerCreateOptions)
|
||||
common.DefineCreateFlags(cmd, &updateOptions.ContainerCreateOptions, entities.UpdateMode)
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -53,12 +58,14 @@ func init() {
|
||||
Command: updateCommand,
|
||||
})
|
||||
updateFlags(updateCommand)
|
||||
validate.AddLatestFlag(updateCommand, &updateOptions.Latest)
|
||||
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Command: containerUpdateCommand,
|
||||
Parent: containerCmd,
|
||||
})
|
||||
updateFlags(containerUpdateCommand)
|
||||
validate.AddLatestFlag(containerUpdateCommand, &updateOptions.Latest)
|
||||
}
|
||||
|
||||
func GetChangedHealthCheckConfiguration(cmd *cobra.Command, vals *entities.ContainerCreateOptions) define.UpdateHealthCheckConfig {
|
||||
@ -129,12 +136,12 @@ func update(cmd *cobra.Command, args []string) error {
|
||||
s := &specgen.SpecGenerator{}
|
||||
s.ResourceLimits = &specs.LinuxResources{}
|
||||
|
||||
err = createOrUpdateFlags(cmd, &updateOpts)
|
||||
err = createOrUpdateFlags(cmd, &updateOptions.ContainerCreateOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.ResourceLimits, err = specgenutil.GetResources(s, &updateOpts)
|
||||
s.ResourceLimits, err = specgenutil.GetResources(s, &updateOptions.ContainerCreateOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -143,17 +150,21 @@ func update(cmd *cobra.Command, args []string) error {
|
||||
s.ResourceLimits = &specs.LinuxResources{}
|
||||
}
|
||||
|
||||
healthCheckConfig := GetChangedHealthCheckConfiguration(cmd, &updateOpts)
|
||||
healthCheckConfig := GetChangedHealthCheckConfiguration(cmd, &updateOptions.ContainerCreateOptions)
|
||||
|
||||
opts := &entities.ContainerUpdateOptions{
|
||||
NameOrID: strings.TrimPrefix(args[0], "/"),
|
||||
Resources: s.ResourceLimits,
|
||||
ChangedHealthCheckConfiguration: &healthCheckConfig,
|
||||
DevicesLimits: GetChangedDeviceLimits(s),
|
||||
Latest: updateOptions.Latest,
|
||||
}
|
||||
|
||||
if !updateOptions.Latest {
|
||||
opts.NameOrID = strings.TrimPrefix(args[0], "/")
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("restart") {
|
||||
policy, retries, err := util.ParseRestartPolicy(updateOpts.Restart)
|
||||
policy, retries, err := util.ParseRestartPolicy(updateOptions.Restart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
####> This option file is used in:
|
||||
####> podman attach, container diff, container inspect, diff, exec, init, inspect, kill, logs, mount, network reload, pause, pod inspect, pod kill, pod logs, pod rm, pod start, pod stats, pod stop, pod top, port, restart, rm, start, stats, stop, top, unmount, unpause, wait
|
||||
####> podman attach, container diff, container inspect, diff, exec, init, inspect, kill, logs, mount, network reload, pause, pod inspect, pod kill, pod logs, pod rm, pod start, pod stats, pod stop, pod top, port, restart, rm, start, stats, stop, top, unmount, unpause, update, wait
|
||||
####> If file is edited, make sure the changes
|
||||
####> are applicable to all of those.
|
||||
#### **--latest**, **-l**
|
||||
|
@ -78,6 +78,8 @@ Changing this setting resets the timer, depending on the state of the container.
|
||||
|
||||
@@option health-timeout
|
||||
|
||||
@@option latest
|
||||
|
||||
@@option memory
|
||||
|
||||
@@option memory-reservation
|
||||
@ -102,6 +104,11 @@ Update a container with a new cpu quota and period:
|
||||
podman update --cpus=0.5 ctrID
|
||||
```
|
||||
|
||||
Update the latest container with a new cpu value:
|
||||
```
|
||||
podman update --latest --cpus=1
|
||||
```
|
||||
|
||||
Update a container with multiple options at ones:
|
||||
```
|
||||
podman update --cpus 5 --cpuset-cpus 0 --cpu-shares 123 --cpuset-mems 0 \\
|
||||
@ -116,4 +123,5 @@ podman update --cpus 5 --cpuset-cpus 0 --cpu-shares 123 --cpuset-mems 0 \\
|
||||
**[podman(1)](podman.1.md)**, **[podman-create(1)](podman-create.1.md)**, **[podman-run(1)](podman-run.1.md)**
|
||||
|
||||
## HISTORY
|
||||
June 2025, Latest option added by Hayato Kihara <kai.21banana@gmail.com>
|
||||
August 2022, Originally written by Charlie Doern <cdoern@redhat.com>
|
||||
|
@ -61,6 +61,7 @@ type ContainerUpdateOptions struct {
|
||||
RestartRetries *uint
|
||||
Env []string
|
||||
UnsetEnv []string
|
||||
Latest bool
|
||||
}
|
||||
|
||||
func (u *ContainerUpdateOptions) ProcessSpecgen() {
|
||||
|
@ -1804,7 +1804,7 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti
|
||||
// ContainerUpdate finds and updates the given container's cgroup config with the specified options
|
||||
func (ic *ContainerEngine) ContainerUpdate(ctx context.Context, updateOptions *entities.ContainerUpdateOptions) (string, error) {
|
||||
updateOptions.ProcessSpecgen()
|
||||
containers, err := getContainers(ic.Libpod, getContainersOptions{names: []string{updateOptions.NameOrID}})
|
||||
containers, err := getContainers(ic.Libpod, getContainersOptions{latest: updateOptions.Latest, names: []string{updateOptions.NameOrID}})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -306,4 +306,39 @@ var _ = Describe("Podman update", func() {
|
||||
Expect(env).ToNot(ContainSubstring("FOO"))
|
||||
Expect(env).To(ContainSubstring("PATH="))
|
||||
})
|
||||
|
||||
It("podman update the latest container", func() {
|
||||
SkipIfRemote("--latest is local-only")
|
||||
|
||||
restartPolicyName := ".HostConfig.RestartPolicy.Name"
|
||||
restartPolicyRetries := ".HostConfig.RestartPolicy.MaximumRetryCount"
|
||||
|
||||
// Arrange an old container
|
||||
oldContainerName := "old-container"
|
||||
oldContainer := podmanTest.Podman([]string{"run", "-d", "--name", oldContainerName, ALPINE, "top"})
|
||||
oldContainer.WaitWithDefaultTimeout()
|
||||
Expect(oldContainer).Should(ExitCleanly())
|
||||
|
||||
podmanTest.CheckContainerSingleField(oldContainerName, restartPolicyName, "no")
|
||||
podmanTest.CheckContainerSingleField(oldContainerName, restartPolicyRetries, "0")
|
||||
|
||||
// Arrange a new container
|
||||
newContainerName := "new-container"
|
||||
newContainer := podmanTest.Podman([]string{"run", "-d", "--name", newContainerName, ALPINE, "top"})
|
||||
newContainer.WaitWithDefaultTimeout()
|
||||
Expect(newContainer).Should(ExitCleanly())
|
||||
|
||||
podmanTest.CheckContainerSingleField(newContainerName, restartPolicyName, "no")
|
||||
podmanTest.CheckContainerSingleField(newContainerName, restartPolicyRetries, "0")
|
||||
|
||||
// Test the latest is updated
|
||||
updatedContainer := podmanTest.Podman([]string{"update", "--restart", "on-failure:5", "--latest"})
|
||||
updatedContainer.WaitWithDefaultTimeout()
|
||||
Expect(updatedContainer).Should(ExitCleanly())
|
||||
|
||||
podmanTest.CheckContainerSingleField(oldContainerName, restartPolicyName, "no")
|
||||
podmanTest.CheckContainerSingleField(oldContainerName, restartPolicyRetries, "0")
|
||||
podmanTest.CheckContainerSingleField(newContainerName, restartPolicyName, "on-failure")
|
||||
podmanTest.CheckContainerSingleField(newContainerName, restartPolicyRetries, "5")
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user