MCPcopy
hub / github.com/docker/compose / planRecreateVolume

Method planRecreateVolume

pkg/compose/reconcile.go:276–323  ·  view source on GitHub ↗

planRecreateVolume adds the full sequence for a diverged volume: stop affected containers → remove containers → remove volume → create volume. Containers must be removed (not just stopped) because Docker does not allow removing a volume that is referenced by any container, even a stopped one. nolin

(key string, vol *types.VolumeConfig)

Source from the content-addressed store, hash-verified

274//
275//nolint:unused // see reconciler.prompt field doc — seam consolidation.
276func (r *reconciler) planRecreateVolume(key string, vol *types.VolumeConfig) {
277 observed := r.observed.Volumes[key]
278 affectedServices := r.servicesUsingVolume(key)
279 affectedContainers := r.containersForServices(affectedServices)
280
281 // Stop all affected containers
282 var stopNodes []*PlanNode
283 for i := range affectedContainers {
284 oc := &affectedContainers[i]
285 node := r.plan.addNode(Operation{
286 Type: OpStopContainer,
287 ResourceID: fmt.Sprintf("service:%s:%d", oc.Summary.Labels[api.ServiceLabel], oc.Number),
288 Cause: fmt.Sprintf("volume %s config changed", key),
289 Container: &oc.Summary,
290 }, "")
291 stopNodes = append(stopNodes, node)
292 }
293
294 // Remove all affected containers (each depends on its own stop)
295 var removeNodes []*PlanNode
296 for i, oc := range affectedContainers {
297 node := r.plan.addNode(Operation{
298 Type: OpRemoveContainer,
299 ResourceID: fmt.Sprintf("service:%s:%d", oc.Summary.Labels[api.ServiceLabel], oc.Number),
300 Cause: fmt.Sprintf("volume %s config changed", key),
301 Container: &affectedContainers[i].Summary,
302 }, "", stopNodes[i])
303 removeNodes = append(removeNodes, node)
304 }
305
306 // Remove the *observed* volume (depends on all container removals)
307 removeVolNode := r.plan.addNode(Operation{
308 Type: OpRemoveVolume,
309 ResourceID: fmt.Sprintf("volume:%s", key),
310 Cause: "config hash diverged",
311 Name: observed.Name,
312 }, "", removeNodes...)
313
314 // Create volume (depends on remove)
315 createNode := r.plan.addNode(Operation{
316 Type: OpCreateVolume,
317 ResourceID: fmt.Sprintf("volume:%s", key),
318 Cause: "recreate after config change",
319 Name: vol.Name,
320 Volume: vol,
321 }, "", removeVolNode)
322 r.volumeNodes[key] = createNode
323}
324
325// servicesUsingNetwork returns the names of services that reference the given
326// compose network key, sorted for deterministic plan output.

Callers

nothing calls this directly

Calls 3

servicesUsingVolumeMethod · 0.95
containersForServicesMethod · 0.95
addNodeMethod · 0.80

Tested by

no test coverage detected