mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-08-13 20:29:35 +00:00
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>
199 lines
6.3 KiB
Go
199 lines
6.3 KiB
Go
package containers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"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"
|
|
"github.com/containers/podman/v5/pkg/specgenutil"
|
|
"github.com/containers/podman/v5/pkg/util"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
updateDescription = `Updates the configuration of an existing container, allowing changes to resource limits and healthchecks`
|
|
|
|
updateCommand = &cobra.Command{
|
|
Use: "update [options] CONTAINER",
|
|
Short: "Update an existing container",
|
|
Long: updateDescription,
|
|
RunE: update,
|
|
Args: validate.IDOrLatestArgs,
|
|
ValidArgsFunction: common.AutocompleteContainers,
|
|
Example: `podman update --cpus=5 foobar_container`,
|
|
}
|
|
|
|
containerUpdateCommand = &cobra.Command{
|
|
Args: updateCommand.Args,
|
|
Use: updateCommand.Use,
|
|
Short: updateCommand.Short,
|
|
Long: updateCommand.Long,
|
|
RunE: updateCommand.RunE,
|
|
ValidArgsFunction: updateCommand.ValidArgsFunction,
|
|
Example: `podman container update --cpus=5 foobar_container`,
|
|
}
|
|
)
|
|
|
|
type ContainerUpdateOptions struct {
|
|
entities.ContainerCreateOptions
|
|
Latest bool
|
|
}
|
|
|
|
var updateOptions ContainerUpdateOptions
|
|
|
|
func updateFlags(cmd *cobra.Command) {
|
|
common.DefineCreateDefaults(&updateOptions.ContainerCreateOptions)
|
|
common.DefineCreateFlags(cmd, &updateOptions.ContainerCreateOptions, entities.UpdateMode)
|
|
}
|
|
|
|
func init() {
|
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
|
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 {
|
|
updateHealthCheckConfig := define.UpdateHealthCheckConfig{}
|
|
|
|
if cmd.Flags().Changed("health-log-destination") {
|
|
updateHealthCheckConfig.HealthLogDestination = &vals.HealthLogDestination
|
|
}
|
|
if cmd.Flags().Changed("health-max-log-size") {
|
|
updateHealthCheckConfig.HealthMaxLogSize = &vals.HealthMaxLogSize
|
|
}
|
|
if cmd.Flags().Changed("health-max-log-count") {
|
|
updateHealthCheckConfig.HealthMaxLogCount = &vals.HealthMaxLogCount
|
|
}
|
|
if cmd.Flags().Changed("health-on-failure") {
|
|
updateHealthCheckConfig.HealthOnFailure = &vals.HealthOnFailure
|
|
}
|
|
if cmd.Flags().Changed("no-healthcheck") {
|
|
updateHealthCheckConfig.NoHealthCheck = &vals.NoHealthCheck
|
|
}
|
|
if cmd.Flags().Changed("health-cmd") {
|
|
updateHealthCheckConfig.HealthCmd = &vals.HealthCmd
|
|
}
|
|
if cmd.Flags().Changed("health-interval") {
|
|
updateHealthCheckConfig.HealthInterval = &vals.HealthInterval
|
|
}
|
|
if cmd.Flags().Changed("health-retries") {
|
|
updateHealthCheckConfig.HealthRetries = &vals.HealthRetries
|
|
}
|
|
if cmd.Flags().Changed("health-timeout") {
|
|
updateHealthCheckConfig.HealthTimeout = &vals.HealthTimeout
|
|
}
|
|
if cmd.Flags().Changed("health-start-period") {
|
|
updateHealthCheckConfig.HealthStartPeriod = &vals.HealthStartPeriod
|
|
}
|
|
if cmd.Flags().Changed("health-startup-cmd") {
|
|
updateHealthCheckConfig.HealthStartupCmd = &vals.StartupHCCmd
|
|
}
|
|
if cmd.Flags().Changed("health-startup-interval") {
|
|
updateHealthCheckConfig.HealthStartupInterval = &vals.StartupHCInterval
|
|
}
|
|
if cmd.Flags().Changed("health-startup-retries") {
|
|
updateHealthCheckConfig.HealthStartupRetries = &vals.StartupHCRetries
|
|
}
|
|
if cmd.Flags().Changed("health-startup-timeout") {
|
|
updateHealthCheckConfig.HealthStartupTimeout = &vals.StartupHCTimeout
|
|
}
|
|
if cmd.Flags().Changed("health-startup-success") {
|
|
updateHealthCheckConfig.HealthStartupSuccess = &vals.StartupHCSuccesses
|
|
}
|
|
|
|
return updateHealthCheckConfig
|
|
}
|
|
|
|
func GetChangedDeviceLimits(s *specgen.SpecGenerator) *define.UpdateContainerDevicesLimits {
|
|
updateDevicesLimits := define.UpdateContainerDevicesLimits{}
|
|
updateDevicesLimits.SetBlkIOWeightDevice(s.WeightDevice)
|
|
updateDevicesLimits.SetDeviceReadBPs(s.ThrottleReadBpsDevice)
|
|
updateDevicesLimits.SetDeviceWriteBPs(s.ThrottleWriteBpsDevice)
|
|
updateDevicesLimits.SetDeviceReadIOPs(s.ThrottleReadIOPSDevice)
|
|
updateDevicesLimits.SetDeviceWriteIOPs(s.ThrottleWriteIOPSDevice)
|
|
return &updateDevicesLimits
|
|
}
|
|
|
|
func update(cmd *cobra.Command, args []string) error {
|
|
var err error
|
|
// use a specgen since this is the easiest way to hold resource info
|
|
s := &specgen.SpecGenerator{}
|
|
s.ResourceLimits = &specs.LinuxResources{}
|
|
|
|
err = createOrUpdateFlags(cmd, &updateOptions.ContainerCreateOptions)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
s.ResourceLimits, err = specgenutil.GetResources(s, &updateOptions.ContainerCreateOptions)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if s.ResourceLimits == nil {
|
|
s.ResourceLimits = &specs.LinuxResources{}
|
|
}
|
|
|
|
healthCheckConfig := GetChangedHealthCheckConfiguration(cmd, &updateOptions.ContainerCreateOptions)
|
|
|
|
opts := &entities.ContainerUpdateOptions{
|
|
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(updateOptions.Restart)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
opts.RestartPolicy = &policy
|
|
if policy == define.RestartPolicyOnFailure {
|
|
opts.RestartRetries = &retries
|
|
}
|
|
}
|
|
|
|
if cmd.Flags().Changed("env") {
|
|
env, err := cmd.Flags().GetStringArray("env")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
opts.Env = env
|
|
}
|
|
|
|
if cmd.Flags().Changed("unsetenv") {
|
|
env, err := cmd.Flags().GetStringArray("unsetenv")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
opts.UnsetEnv = env
|
|
}
|
|
|
|
rep, err := registry.ContainerEngine().ContainerUpdate(context.Background(), opts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println(rep)
|
|
return nil
|
|
}
|