// ServiceNodes returns all the nodes registered as part of a service func (c *Catalog) ServiceNodes(args *structs.ServiceSpecificRequest, reply *structs.IndexedServiceNodes) error { if done, err := c.srv.forward("Catalog.ServiceNodes", args, args, reply); done { return err } // Verify the arguments if args.ServiceName == "" { return fmt.Errorf("Must provide service name") } // Get the nodes state := c.srv.fsm.State() err := c.srv.blockingRPC( &args.QueryOptions, &reply.QueryMeta, state.GetQueryWatch("ServiceNodes"), func() error { var index uint64 var services structs.ServiceNodes var err error if args.TagFilter { index, services, err = state.ServiceTagNodes(args.ServiceName, args.ServiceTag) } else { index, services, err = state.ServiceNodes(args.ServiceName) } if err != nil { return err } reply.Index, reply.ServiceNodes = index, services if len(args.NodeMetaFilters) > 0 { var filtered structs.ServiceNodes for _, service := range services { if structs.SatisfiesMetaFilters(service.NodeMeta, args.NodeMetaFilters) { filtered = append(filtered, service) } } reply.ServiceNodes = filtered } if err := c.srv.filterACL(args.Token, reply); err != nil { return err } return c.srv.sortNodesByDistanceFrom(args.Source, reply.ServiceNodes) }) // Provide some metrics if err == nil { metrics.IncrCounter([]string{"consul", "catalog", "service", "query", args.ServiceName}, 1) if args.ServiceTag != "" { metrics.IncrCounter([]string{"consul", "catalog", "service", "query-tag", args.ServiceName, args.ServiceTag}, 1) } if len(reply.ServiceNodes) == 0 { metrics.IncrCounter([]string{"consul", "catalog", "service", "not-found", args.ServiceName}, 1) } } return err }
func (s *HTTPServer) CatalogServiceNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) { // Set default DC args := structs.ServiceSpecificRequest{} s.parseSource(req, &args.Source) args.NodeMetaFilters = s.parseMetaFilter(req) if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done { return nil, nil } // Check for a tag params := req.URL.Query() if _, ok := params["tag"]; ok { args.ServiceTag = params.Get("tag") args.TagFilter = true } // Pull out the service name args.ServiceName = strings.TrimPrefix(req.URL.Path, "/v1/catalog/service/") if args.ServiceName == "" { resp.WriteHeader(400) resp.Write([]byte("Missing service name")) return nil, nil } // Make the RPC request var out structs.IndexedServiceNodes defer setMeta(resp, &out.QueryMeta) if err := s.agent.RPC("Catalog.ServiceNodes", &args, &out); err != nil { return nil, err } translateAddresses(s.agent.config, args.Datacenter, out.ServiceNodes) // Use empty list instead of nil if out.ServiceNodes == nil { out.ServiceNodes = make(structs.ServiceNodes, 0) } return out.ServiceNodes, nil }