Add support for updating restart policy

This is something Docker does, and we did not do until now. Most
difficult/annoying part was the REST API, where I did not really
want to modify the struct being sent, so I made the new restart
policy parameters query parameters instead.

Testing was also a bit annoying, because testing restart policy
always is.

Signed-off-by: Matt Heon <mheon@redhat.com>
This commit is contained in:
Matt Heon
2024-04-11 16:38:13 -04:00
parent ddea30e40e
commit 482ef7bfcf
19 changed files with 278 additions and 137 deletions

View File

@ -2514,22 +2514,55 @@ func (c *Container) extractSecretToCtrStorage(secr *ContainerSecret) error {
return nil
}
// Update a container's resources after creation
func (c *Container) update(resources *spec.LinuxResources) error {
oldResources := c.config.Spec.Linux.Resources
if c.config.Spec.Linux == nil {
c.config.Spec.Linux = new(spec.Linux)
// Update a container's resources or restart policy after creation.
// At least one of resources or restartPolicy must not be nil.
func (c *Container) update(resources *spec.LinuxResources, restartPolicy *string, restartRetries *uint) error {
if resources == nil && restartPolicy == nil {
return fmt.Errorf("must provide at least one of resources and restartPolicy to update a container: %w", define.ErrInvalidArg)
}
if restartRetries != nil && restartPolicy == nil {
return fmt.Errorf("must provide restart policy if updating restart retries: %w", define.ErrInvalidArg)
}
oldResources := c.config.Spec.Linux.Resources
oldRestart := c.config.RestartPolicy
oldRetries := c.config.RestartRetries
if restartPolicy != nil {
if err := define.ValidateRestartPolicy(*restartPolicy); err != nil {
return err
}
if restartRetries != nil {
if *restartPolicy != define.RestartPolicyOnFailure {
return fmt.Errorf("cannot set restart policy retries unless policy is on-failure: %w", define.ErrInvalidArg)
}
}
c.config.RestartPolicy = *restartPolicy
if restartRetries != nil {
c.config.RestartRetries = *restartRetries
} else {
c.config.RestartRetries = 0
}
}
if resources != nil {
if c.config.Spec.Linux == nil {
c.config.Spec.Linux = new(spec.Linux)
}
c.config.Spec.Linux.Resources = resources
}
c.config.Spec.Linux.Resources = resources
if err := c.runtime.state.SafeRewriteContainerConfig(c, "", "", c.config); err != nil {
// Assume DB write failed, revert to old resources block
c.config.Spec.Linux.Resources = oldResources
c.config.RestartPolicy = oldRestart
c.config.RestartRetries = oldRetries
return err
}
if c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStatePaused) {
if c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStatePaused) && resources != nil {
// So `podman inspect` on running containers sources its OCI spec from disk.
// To keep inspect accurate we need to update the on-disk OCI spec.
onDiskSpec, err := c.specFromState()