github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/daemon/update.go (about) 1 package daemon 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/docker/docker/api/types/container" 8 "github.com/docker/docker/errdefs" 9 "github.com/pkg/errors" 10 ) 11 12 // ContainerUpdate updates configuration of the container 13 func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error) { 14 var warnings []string 15 16 c, err := daemon.GetContainer(name) 17 if err != nil { 18 return container.ContainerUpdateOKBody{Warnings: warnings}, err 19 } 20 21 warnings, err = daemon.verifyContainerSettings(c.OS, hostConfig, nil, true) 22 if err != nil { 23 return container.ContainerUpdateOKBody{Warnings: warnings}, errdefs.InvalidParameter(err) 24 } 25 26 if err := daemon.update(name, hostConfig); err != nil { 27 return container.ContainerUpdateOKBody{Warnings: warnings}, err 28 } 29 30 return container.ContainerUpdateOKBody{Warnings: warnings}, nil 31 } 32 33 func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) error { 34 if hostConfig == nil { 35 return nil 36 } 37 38 container, err := daemon.GetContainer(name) 39 if err != nil { 40 return err 41 } 42 43 restoreConfig := false 44 backupHostConfig := *container.HostConfig 45 defer func() { 46 if restoreConfig { 47 container.Lock() 48 container.HostConfig = &backupHostConfig 49 container.CheckpointTo(daemon.containersReplica) 50 container.Unlock() 51 } 52 }() 53 54 if container.RemovalInProgress || container.Dead { 55 return errCannotUpdate(container.ID, fmt.Errorf("container is marked for removal and cannot be \"update\"")) 56 } 57 58 container.Lock() 59 if err := container.UpdateContainer(hostConfig); err != nil { 60 restoreConfig = true 61 container.Unlock() 62 return errCannotUpdate(container.ID, err) 63 } 64 if err := container.CheckpointTo(daemon.containersReplica); err != nil { 65 restoreConfig = true 66 container.Unlock() 67 return errCannotUpdate(container.ID, err) 68 } 69 container.Unlock() 70 71 // if Restart Policy changed, we need to update container monitor 72 if hostConfig.RestartPolicy.Name != "" { 73 container.UpdateMonitor(hostConfig.RestartPolicy) 74 } 75 76 // If container is not running, update hostConfig struct is enough, 77 // resources will be updated when the container is started again. 78 // If container is running (including paused), we need to update configs 79 // to the real world. 80 if container.IsRunning() && !container.IsRestarting() { 81 if err := daemon.containerd.UpdateResources(context.Background(), container.ID, toContainerdResources(hostConfig.Resources)); err != nil { 82 restoreConfig = true 83 // TODO: it would be nice if containerd responded with better errors here so we can classify this better. 84 return errCannotUpdate(container.ID, errdefs.System(err)) 85 } 86 } 87 88 daemon.LogContainerEvent(container, "update") 89 90 return nil 91 } 92 93 func errCannotUpdate(containerID string, err error) error { 94 return errors.Wrap(err, "Cannot update container "+containerID) 95 }