Merge pull request #9912 from justinsb/loadbalancer_logic

servicecontroller: last state applied to LB vs last state seen
This commit is contained in:
Saad Ali 2015-06-16 18:32:56 -07:00
commit 185eb5e26a
2 changed files with 15 additions and 8 deletions

View File

@ -52,7 +52,11 @@ const (
) )
type cachedService struct { type cachedService struct {
service *api.Service // The last-known state of the service
lastState *api.Service
// The state as successfully applied to the load balancer
appliedState *api.Service
// Ensures only one goroutine can operate on this service at any given time. // Ensures only one goroutine can operate on this service at any given time.
mu sync.Mutex mu sync.Mutex
} }
@ -191,8 +195,8 @@ func (s *ServiceController) processDelta(delta *cache.Delta) (error, bool) {
if !ok { if !ok {
return fmt.Errorf("Service %s not in cache even though the watcher thought it was. Ignoring the deletion.", key), notRetryable return fmt.Errorf("Service %s not in cache even though the watcher thought it was. Ignoring the deletion.", key), notRetryable
} }
service = cachedService.service service = cachedService.lastState
delta.Object = cachedService.service delta.Object = cachedService.lastState
namespacedName = types.NamespacedName{service.Namespace, service.Name} namespacedName = types.NamespacedName{service.Namespace, service.Name}
} else { } else {
namespacedName.Namespace = service.Namespace namespacedName.Namespace = service.Namespace
@ -206,6 +210,9 @@ func (s *ServiceController) processDelta(delta *cache.Delta) (error, bool) {
cachedService.mu.Lock() cachedService.mu.Lock()
defer cachedService.mu.Unlock() defer cachedService.mu.Unlock()
// Update the cached service (used above for populating synthetic deletes)
cachedService.lastState = service
// TODO: Handle added, updated, and sync differently? // TODO: Handle added, updated, and sync differently?
switch delta.Type { switch delta.Type {
case cache.Added: case cache.Added:
@ -213,7 +220,7 @@ func (s *ServiceController) processDelta(delta *cache.Delta) (error, bool) {
case cache.Updated: case cache.Updated:
fallthrough fallthrough
case cache.Sync: case cache.Sync:
err, retry := s.createLoadBalancerIfNeeded(namespacedName, service, cachedService.service) err, retry := s.createLoadBalancerIfNeeded(namespacedName, service, cachedService.appliedState)
if err != nil { if err != nil {
s.eventRecorder.Event(service, "creating loadbalancer failed", err.Error()) s.eventRecorder.Event(service, "creating loadbalancer failed", err.Error())
return err, retry return err, retry
@ -222,7 +229,7 @@ func (s *ServiceController) processDelta(delta *cache.Delta) (error, bool) {
// NOTE: Since we update the cached service if and only if we successully // 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 // processed it, a cached service being nil implies that it hasn't yet
// been successfully processed. // been successfully processed.
cachedService.service = service cachedService.appliedState = service
s.cache.set(namespacedName.String(), cachedService) s.cache.set(namespacedName.String(), cachedService)
case cache.Deleted: case cache.Deleted:
err := s.balancer.EnsureTCPLoadBalancerDeleted(s.loadBalancerName(service), s.zone.Region) err := s.balancer.EnsureTCPLoadBalancerDeleted(s.loadBalancerName(service), s.zone.Region)
@ -609,10 +616,10 @@ func (s *ServiceController) updateLoadBalancerHosts(services []*cachedService, h
// with by the load balancer reconciler. We can trust the load balancer // with by the load balancer reconciler. We can trust the load balancer
// reconciler to ensure the service's load balancer is created to target // reconciler to ensure the service's load balancer is created to target
// the correct nodes. // the correct nodes.
if service.service == nil { if service.appliedState == nil {
return return
} }
if err := s.lockedUpdateLoadBalancerHosts(service.service, hosts); err != nil { if err := s.lockedUpdateLoadBalancerHosts(service.appliedState, hosts); err != nil {
glog.Errorf("External error while updating TCP load balancer: %v.", err) glog.Errorf("External error while updating TCP load balancer: %v.", err)
servicesToRetry = append(servicesToRetry, service) servicesToRetry = append(servicesToRetry, service)
} }

View File

@ -206,7 +206,7 @@ func TestUpdateNodesInExternalLoadBalancer(t *testing.T) {
var services []*cachedService var services []*cachedService
for _, service := range item.services { for _, service := range item.services {
services = append(services, &cachedService{service: service}) services = append(services, &cachedService{lastState: service, appliedState: service})
} }
if err := controller.updateLoadBalancerHosts(services, hosts); err != nil { if err := controller.updateLoadBalancerHosts(services, hosts); err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)