planRecreateNetwork adds the full sequence for a diverged network: stop affected containers → disconnect → remove network → create network.
(key string, nw *types.NetworkConfig)
| 184 | // planRecreateNetwork adds the full sequence for a diverged network: |
| 185 | // stop affected containers → disconnect → remove network → create network. |
| 186 | func (r *reconciler) planRecreateNetwork(key string, nw *types.NetworkConfig) error { |
| 187 | observed := r.observed.Networks[key] |
| 188 | affectedServices := r.servicesUsingNetwork(key) |
| 189 | affectedContainers := r.containersForServices(affectedServices) |
| 190 | |
| 191 | // Stop all affected containers, recording each Stop node so that a later |
| 192 | // recreate of the same container does not emit a second Stop against a |
| 193 | // container that is already stopped. |
| 194 | var stopNodes []*PlanNode |
| 195 | for i := range affectedContainers { |
| 196 | oc := &affectedContainers[i] |
| 197 | node := r.plan.addNode(Operation{ |
| 198 | Type: OpStopContainer, |
| 199 | ResourceID: fmt.Sprintf("service:%s:%d", oc.Summary.Labels[api.ServiceLabel], oc.Number), |
| 200 | Cause: fmt.Sprintf("network %s config changed", key), |
| 201 | Container: &oc.Summary, |
| 202 | }, "") |
| 203 | stopNodes = append(stopNodes, node) |
| 204 | r.stoppedByPlan[oc.ID] = node |
| 205 | } |
| 206 | |
| 207 | // Disconnect all affected containers from the *observed* network (each depends on its own stop) |
| 208 | var disconnectNodes []*PlanNode |
| 209 | for i, oc := range affectedContainers { |
| 210 | node := r.plan.addNode(Operation{ |
| 211 | Type: OpDisconnectNetwork, |
| 212 | ResourceID: fmt.Sprintf("service:%s:%d", oc.Summary.Labels[api.ServiceLabel], oc.Number), |
| 213 | Cause: fmt.Sprintf("network %s recreate", key), |
| 214 | Container: &affectedContainers[i].Summary, |
| 215 | Name: observed.Name, |
| 216 | }, "", stopNodes[i]) |
| 217 | disconnectNodes = append(disconnectNodes, node) |
| 218 | } |
| 219 | |
| 220 | // Remove the *observed* network (depends on all disconnects) |
| 221 | removeNode := r.plan.addNode(Operation{ |
| 222 | Type: OpRemoveNetwork, |
| 223 | ResourceID: fmt.Sprintf("network:%s", key), |
| 224 | Cause: "config hash diverged", |
| 225 | Name: observed.Name, |
| 226 | }, "", disconnectNodes...) |
| 227 | |
| 228 | // Create network (depends on remove) |
| 229 | createNode := r.plan.addNode(Operation{ |
| 230 | Type: OpCreateNetwork, |
| 231 | ResourceID: fmt.Sprintf("network:%s", key), |
| 232 | Cause: "recreate after config change", |
| 233 | Name: nw.Name, |
| 234 | Network: nw, |
| 235 | }, "", removeNode) |
| 236 | r.networkNodes[key] = createNode |
| 237 | |
| 238 | return nil |
| 239 | } |
| 240 | |
| 241 | // reconcileVolumes adds plan nodes for volume creation. Recreation of a |
| 242 | // diverged volume is handled by ensureProjectVolumes (which already prompts |
no test coverage detected