Properly handle nil cached services in the service controller's node reconciler.

Add a test that catches the former bug.
This commit is contained in:
Alex Robinson 2015-05-17 22:36:48 -07:00
parent efb42b302d
commit 3cf80e76c8
2 changed files with 21 additions and 1 deletions

View File

@ -203,7 +203,10 @@ func (s *ServiceController) processDelta(delta *cache.Delta) (error, bool) {
if err != nil {
return err, retry
}
// Always update the cache upon success
// Always update the cache upon success.
// NOTE: Since we update the cached service if and only if we successully
// processed it, a cached service being nil implies that it hasn't yet
// been successfully processed.
cachedService.service = service
s.cache.set(namespacedName.String(), cachedService)
case cache.Deleted:
@ -554,6 +557,13 @@ func (s *ServiceController) updateLoadBalancerHosts(services []*cachedService, h
func() {
service.mu.Lock()
defer service.mu.Unlock()
// If the service is nil, that means it hasn't yet been successfully dealt
// with by the load balancer reconciler. We can trust the load balancer
// reconciler to ensure the service's load balancer is created to target
// the correct nodes.
if service.service == nil {
return
}
if err := s.lockedUpdateLoadBalancerHosts(service.service, hosts); err != nil {
glog.Errorf("External error while updating TCP load balancer: %v.", err)
servicesToRetry = append(servicesToRetry, service)

View File

@ -184,6 +184,16 @@ func TestUpdateNodesInExternalLoadBalancer(t *testing.T) {
{Name: "a999", Region: region, Hosts: []string{"node0", "node1", "node73"}},
},
},
{
// One service has an external load balancer and one is nil: one call.
services: []*api.Service{
newService("s0", "234", true),
nil,
},
expectedUpdateCalls: []fake_cloud.FakeUpdateBalancerCall{
{Name: "a234", Region: region, Hosts: []string{"node0", "node1", "node73"}},
},
},
}
for _, item := range table {
cloud := &fake_cloud.FakeCloud{}