// OnUpdate manages the registered service endpoints. // Registered endpoints are updated if found in the update set or // unregistered if missing from the update set. func (lb *LoadBalancerRR) OnUpdate(allEndpoints []api.Endpoints) { registeredEndpoints := make(map[ServicePortName]bool) lb.lock.Lock() defer lb.lock.Unlock() // Update endpoints for services. for i := range allEndpoints { svcEndpoints := &allEndpoints[i] // We need to build a map of portname -> all ip:ports for that // portname. Explode Endpoints.Subsets[*] into this structure. portsToEndpoints := map[string][]hostPortPair{} for i := range svcEndpoints.Subsets { ss := &svcEndpoints.Subsets[i] for i := range ss.Ports { port := &ss.Ports[i] for i := range ss.Addresses { addr := &ss.Addresses[i] portsToEndpoints[port.Name] = append(portsToEndpoints[port.Name], hostPortPair{addr.IP, port.Port}) // Ignore the protocol field - we'll get that from the Service objects. } } } for portname := range portsToEndpoints { svcPort := ServicePortName{types.NamespacedName{svcEndpoints.Namespace, svcEndpoints.Name}, portname} state, exists := lb.services[svcPort] curEndpoints := []string{} if state != nil { curEndpoints = state.endpoints } newEndpoints := flattenValidEndpoints(portsToEndpoints[portname]) if !exists || state == nil || len(curEndpoints) != len(newEndpoints) || !slicesEquiv(slice.CopyStrings(curEndpoints), newEndpoints) { glog.V(1).Infof("LoadBalancerRR: Setting endpoints for %s to %+v", svcPort, newEndpoints) lb.updateAffinityMap(svcPort, newEndpoints) // OnUpdate can be called without NewService being called externally. // To be safe we will call it here. A new service will only be created // if one does not already exist. state = lb.newServiceInternal(svcPort, api.AffinityTypeNone, 0) state.endpoints = slice.ShuffleStrings(newEndpoints) // Reset the round-robin index. state.index = 0 } registeredEndpoints[svcPort] = true } } // Remove endpoints missing from the update. for k := range lb.services { if _, exists := registeredEndpoints[k]; !exists { glog.V(2).Infof("LoadBalancerRR: Removing endpoints for %s", k) delete(lb.services, k) } } }
// OnUpdate manages the registered service endpoints. // Registered endpoints are updated if found in the update set or // unregistered if missing from the update set. func (lb *LoadBalancerRR) OnUpdate(allEndpoints []api.Endpoints) { registeredEndpoints := make(map[types.NamespacedName]bool) lb.lock.Lock() defer lb.lock.Unlock() // Update endpoints for services. for _, svcEndpoints := range allEndpoints { name := types.NamespacedName{svcEndpoints.Namespace, svcEndpoints.Name} key := name state, exists := lb.services[key] curEndpoints := []string{} if state != nil { curEndpoints = state.endpoints } newEndpoints := filterValidEndpoints(svcEndpoints.Endpoints) if !exists || state == nil || len(curEndpoints) != len(newEndpoints) || !slicesEquiv(slice.CopyStrings(curEndpoints), newEndpoints) { glog.V(3).Infof("LoadBalancerRR: Setting endpoints for %s to %+v", svcEndpoints.Name, svcEndpoints.Endpoints) lb.updateAffinityMap(key, newEndpoints) // On update can be called without NewService being called externally. // To be safe we will call it here. A new service will only be created // if one does not already exist. state = lb.newServiceInternal(name, api.AffinityTypeNone, 0) state.endpoints = slice.ShuffleStrings(newEndpoints) // Reset the round-robin index. state.index = 0 } registeredEndpoints[key] = true } // Remove endpoints missing from the update. for k := range lb.services { if _, exists := registeredEndpoints[k]; !exists { glog.V(3).Infof("LoadBalancerRR: Removing endpoints for %s", k) delete(lb.services, k) } } }