// cp copies a service. Because we're caching handing back pointers would // create a race condition, so we do this instead // its fast enough func (c *cacheSelector) cp(current []*registry.Service) []*registry.Service { var services []*registry.Service for _, service := range current { // copy service s := new(registry.Service) *s = *service // copy nodes var nodes []*registry.Node for _, node := range service.Nodes { n := new(registry.Node) *n = *node nodes = append(nodes, n) } s.Nodes = nodes // copy endpoints var eps []*registry.Endpoint for _, ep := range service.Endpoints { e := new(registry.Endpoint) *e = *ep eps = append(eps, e) } s.Endpoints = eps // append service services = append(services, s) } return services }
// FilterLabel is a label based Select Filter which will // only return services with the label specified. func FilterLabel(key, val string) Filter { return func(old []*registry.Service) []*registry.Service { var services []*registry.Service for _, service := range old { serv := new(registry.Service) var nodes []*registry.Node for _, node := range service.Nodes { if node.Metadata == nil { continue } if node.Metadata[key] == val { nodes = append(nodes, node) } } // only add service if there's some nodes if len(nodes) > 0 { // copy *serv = *service serv.Nodes = nodes services = append(services, serv) } } return services } }
// registers a service against a given pod func register(r registry.Registry, podName string, svc *registry.Service) { os.Setenv("HOSTNAME", podName) pod := setupPod(podName) svc.Nodes = append(svc.Nodes, ®istry.Node{ Id: svc.Name + ":" + pod.Metadata.Name, Address: pod.Status.PodIP, Port: 80, Metadata: map[string]string{}, }) if err := r.Register(svc); err != nil { log.Fatalf("did not expect Register() to fail: %v", err) } os.Setenv("HOSTNAME", "") }
func (r *blacklist) Filter(services []*registry.Service) ([]*registry.Service, error) { var viableServices []*registry.Service r.RLock() for _, service := range services { var viableNodes []*registry.Node for _, node := range service.Nodes { n, ok := r.bl[node.Id] if !ok { // blacklist miss so add it viableNodes = append(viableNodes, node) continue } // got some blacklist info // skip the node if it exceeds count if n.count >= count { continue } // doesn't exceed count, still viable viableNodes = append(viableNodes, node) } if len(viableNodes) == 0 { continue } viableService := new(registry.Service) *viableService = *service viableService.Nodes = viableNodes viableServices = append(viableServices, viableService) } r.RUnlock() return viableServices, nil }
func (c *cacheSelector) update(res *registry.Result) { if res == nil || res.Service == nil { return } c.Lock() defer c.Unlock() services, ok := c.cache[res.Service.Name] if !ok { // we're not going to cache anything // unless there was already a lookup return } if len(res.Service.Nodes) == 0 { switch res.Action { case "delete": c.del(res.Service.Name) } return } // existing service found var service *registry.Service var index int for i, s := range services { if s.Version == res.Service.Version { service = s index = i } } switch res.Action { case "create", "update": if service == nil { c.set(res.Service.Name, append(services, res.Service)) return } // append old nodes to new service for _, cur := range service.Nodes { var seen bool for _, node := range res.Service.Nodes { if cur.Id == node.Id { seen = true break } } if !seen { res.Service.Nodes = append(res.Service.Nodes, cur) } } services[index] = res.Service c.set(res.Service.Name, services) case "delete": if service == nil { return } var nodes []*registry.Node // filter cur nodes to remove the dead one for _, cur := range service.Nodes { var seen bool for _, del := range res.Service.Nodes { if del.Id == cur.Id { seen = true break } } if !seen { nodes = append(nodes, cur) } } // still got nodes, save and return if len(nodes) > 0 { service.Nodes = nodes services[index] = service c.set(service.Name, services) return } // zero nodes left // only have one thing to delete // nuke the thing if len(services) == 1 { c.del(service.Name) return } // still have more than 1 service // check the version and keep what we know var srvs []*registry.Service for _, s := range services { if s.Version != service.Version { srvs = append(srvs, s) } } // save c.set(service.Name, srvs) } }
func (o *os) update(res *registry.Result) { if res == nil || res.Service == nil { return } o.Lock() defer o.Unlock() services, ok := o.cache[res.Service.Name] if !ok { // we're not going to cache anything // unless there was already a lookup return } if len(res.Service.Nodes) == 0 { switch res.Action { case "delete": delete(o.cache, res.Service.Name) } return } // existing service found var service *registry.Service var index int for i, s := range services { if s.Version == res.Service.Version { service = s index = i } } switch res.Action { case "create", "update": if service == nil { services = append(services, res.Service) o.cache[res.Service.Name] = services return } // append old nodes to new service for _, cur := range service.Nodes { var seen bool for _, node := range res.Service.Nodes { if cur.Id == node.Id { seen = true break } } if !seen { res.Service.Nodes = append(res.Service.Nodes, cur) } } services[index] = res.Service o.cache[res.Service.Name] = services case "delete": if service == nil { return } var nodes []*registry.Node // filter cur nodes to remove the dead one for _, cur := range service.Nodes { var seen bool for _, del := range res.Service.Nodes { if del.Id == cur.Id { seen = true break } } if !seen { nodes = append(nodes, cur) } } if len(nodes) == 0 { if len(services) == 1 { delete(o.cache, service.Name) } else { var srvs []*registry.Service for _, s := range services { if s.Version != service.Version { srvs = append(srvs, s) } } o.cache[service.Name] = srvs } return } service.Nodes = nodes services[index] = service o.cache[res.Service.Name] = services } }