Skip to content

Commit 08fc0fc

Browse files
committed
Merge pull request #712 from sanimej/bfix
Handling container rename in libnetwork
2 parents c92c21b + 11512ea commit 08fc0fc

6 files changed

Lines changed: 119 additions & 14 deletions

File tree

controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ type controller struct {
143143
watchCh chan *endpoint
144144
unWatchCh chan *endpoint
145145
svcDb map[string]svcMap
146+
nmap map[string]*netWatch
146147
sync.Mutex
147148
}
148149

endpoint.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,51 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
431431
return sb.clearDefaultGW()
432432
}
433433

434+
func (ep *endpoint) rename(name string) error {
435+
var err error
436+
n := ep.getNetwork()
437+
if n == nil {
438+
return fmt.Errorf("network not connected for ep %q", ep.name)
439+
}
440+
441+
n.getController().Lock()
442+
netWatch, ok := n.getController().nmap[n.ID()]
443+
n.getController().Unlock()
444+
445+
if !ok {
446+
return fmt.Errorf("watch null for network %q", n.Name())
447+
}
448+
449+
n.updateSvcRecord(ep, n.getController().getLocalEps(netWatch), false)
450+
451+
oldName := ep.name
452+
ep.name = name
453+
454+
n.updateSvcRecord(ep, n.getController().getLocalEps(netWatch), true)
455+
defer func() {
456+
if err != nil {
457+
n.updateSvcRecord(ep, n.getController().getLocalEps(netWatch), false)
458+
ep.name = oldName
459+
n.updateSvcRecord(ep, n.getController().getLocalEps(netWatch), true)
460+
}
461+
}()
462+
463+
// Update the store with the updated name
464+
if err = n.getController().updateToStore(ep); err != nil {
465+
return err
466+
}
467+
// After the name change do a dummy endpoint count update to
468+
// trigger the service record update in the peer nodes
469+
470+
// Ignore the error because updateStore fail for EpCnt is a
471+
// benign error. Besides there is no meaningful recovery that
472+
// we can do. When the cluster recovers subsequent EpCnt update
473+
// will force the peers to get the correct EP name.
474+
_ = n.getEpCnt().updateStore()
475+
476+
return err
477+
}
478+
434479
func (ep *endpoint) hasInterface(iName string) bool {
435480
ep.Lock()
436481
defer ep.Unlock()

endpoint_cnt.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,25 @@ func (ec *endpointCnt) EndpointCnt() uint64 {
108108
return ec.Count
109109
}
110110

111+
func (ec *endpointCnt) updateStore() error {
112+
retry:
113+
store := ec.n.getController().getStore(ec.DataScope())
114+
if store == nil {
115+
return fmt.Errorf("store not found for scope %s", ec.DataScope())
116+
}
117+
118+
if err := ec.n.getController().updateToStore(ec); err != nil {
119+
if err == datastore.ErrKeyModified {
120+
if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
121+
return fmt.Errorf("could not update the kvobject to latest on rename: %v", err)
122+
}
123+
goto retry
124+
}
125+
return err
126+
}
127+
return nil
128+
}
129+
111130
func (ec *endpointCnt) atomicIncDecEpCnt(inc bool) error {
112131
retry:
113132
ec.Lock()

libnetwork_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,10 @@ func (f *fakeSandbox) Delete() error {
11341134
return nil
11351135
}
11361136

1137+
func (f *fakeSandbox) Rename(name string) error {
1138+
return nil
1139+
}
1140+
11371141
func (f *fakeSandbox) SetKey(key string) error {
11381142
return nil
11391143
}

sandbox.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ type Sandbox interface {
3434
Refresh(options ...SandboxOption) error
3535
// SetKey updates the Sandbox Key
3636
SetKey(key string) error
37+
// Rename changes the name of all attached Endpoints
38+
Rename(name string) error
3739
// Delete destroys this container after detaching it from all connected endpoints.
3840
Delete() error
3941
}
@@ -201,6 +203,35 @@ func (sb *sandbox) Delete() error {
201203
return nil
202204
}
203205

206+
func (sb *sandbox) Rename(name string) error {
207+
var err error
208+
undo := []func(){}
209+
210+
for _, ep := range sb.getConnectedEndpoints() {
211+
if ep.endpointInGWNetwork() {
212+
continue
213+
}
214+
215+
oldName := ep.Name()
216+
lEp := ep
217+
if err = ep.rename(name); err != nil {
218+
break
219+
}
220+
undo = append(undo,
221+
func() {
222+
// Ignore the error while undoing
223+
_ = lEp.rename(oldName)
224+
})
225+
}
226+
227+
if err != nil {
228+
for _, f := range undo {
229+
f()
230+
}
231+
}
232+
return err
233+
}
234+
204235
func (sb *sandbox) Refresh(options ...SandboxOption) error {
205236
// Store connected endpoints
206237
epList := sb.getConnectedEndpoints()

store.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -274,25 +274,30 @@ func (c *controller) networkWatchLoop(nw *netWatch, ep *endpoint, ecCh <-chan da
274274
continue
275275
}
276276

277-
if _, ok := nw.remoteEps[lEp.ID()]; ok {
278-
delete(delEpMap, lEp.ID())
279-
continue
277+
if ep, ok := nw.remoteEps[lEp.ID()]; ok {
278+
// On a container rename EP ID will remain
279+
// the same but the name will change. service
280+
// records should reflect the change.
281+
// Keep old EP entry in the delEpMap and add
282+
// EP from the store (which has the new name)
283+
// into the new list
284+
if lEp.name == ep.name {
285+
delete(delEpMap, lEp.ID())
286+
continue
287+
}
280288
}
281-
282289
nw.remoteEps[lEp.ID()] = lEp
283290
addEp = append(addEp, lEp)
284-
285291
}
286292
c.Unlock()
287293

288-
for _, lEp := range addEp {
289-
ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), true)
290-
}
291-
292294
for _, lEp := range delEpMap {
293295
ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), false)
294296

295297
}
298+
for _, lEp := range addEp {
299+
ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), true)
300+
}
296301
}
297302
}
298303
}
@@ -378,21 +383,21 @@ func (c *controller) processEndpointDelete(nmap map[string]*netWatch, ep *endpoi
378383
c.Unlock()
379384
}
380385

381-
func (c *controller) watchLoop(nmap map[string]*netWatch) {
386+
func (c *controller) watchLoop() {
382387
for {
383388
select {
384389
case ep := <-c.watchCh:
385-
c.processEndpointCreate(nmap, ep)
390+
c.processEndpointCreate(c.nmap, ep)
386391
case ep := <-c.unWatchCh:
387-
c.processEndpointDelete(nmap, ep)
392+
c.processEndpointDelete(c.nmap, ep)
388393
}
389394
}
390395
}
391396

392397
func (c *controller) startWatch() {
393398
c.watchCh = make(chan *endpoint)
394399
c.unWatchCh = make(chan *endpoint)
395-
nmap := make(map[string]*netWatch)
400+
c.nmap = make(map[string]*netWatch)
396401

397-
go c.watchLoop(nmap)
402+
go c.watchLoop()
398403
}

0 commit comments

Comments
 (0)