code: func (c *Cluster) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error {
  	c.mu.RLock()
  	attacher, ok := c.attachers[attacherKey(networkName, containerID)]
  	if !ok {
  		attacher, ok = c.attachers[attacherKey(networkID, containerID)]
  	}
  	state := c.currentNodeState()
  	if state.swarmNode == nil || state.swarmNode.Agent() == nil {
  		c.mu.RUnlock()
  		return errors.New("invalid cluster node while waiting for detachment")
  	}
  
  	c.mu.RUnlock()
  	agent := state.swarmNode.Agent()
  	if ok && attacher != nil &&
  		attacher.detachWaitCh != nil &&
  		attacher.attachCompleteCh != nil {
  		// Attachment may be in progress still so wait for
  		// attachment to complete.
  		select {
  		case <-attacher.attachCompleteCh:
  		case <-ctx.Done():
  			return ctx.Err()
  		}
  
  		if attacher.taskID == taskID {
  			select {
  			case <-attacher.detachWaitCh:
  			case <-ctx.Done():
  				return ctx.Err()
  			}
  		}
  	}
  
  	return agent.ResourceAllocator().DetachNetwork(ctx, taskID)
  }
docs: // WaitForDetachment waits for the container to stop or detach from
  // the network.