Backport of NET-4135 - Fix NodeMeta filtering Catalog List Services API into release/1.16.x (#19113)
* backport of commit cef8e3d27b2bab062d44e8d55f40a2e97c8efe3b * NET-4135 - Fix NodeMeta filtering Catalog List Services API (#18322) * logs for debugging * Init * white spaces fix * added change log * Fix tests * fix typo * using queryoptionfilter to populate args.filter * tests * fix test * fix tests * fix tests * fix tests * fix tests * fix variable name * fix tests * fix tests * fix tests * Update .changelog/18322.txt Co-authored-by: Ganesh S <ganesh.seetharaman@hashicorp.com> * fix change log * address nits * removed unused line * doing join only when filter has nodemeta * fix tests * fix tests * Update agent/consul/catalog_endpoint.go Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * fix tests * removed unwanted code --------- Co-authored-by: Ganesh S <ganesh.seetharaman@hashicorp.com> Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * removed unwanted log lines * removed unwanted log lines --------- Co-authored-by: absolutelightning <ashesh.vidyut@hashicorp.com> Co-authored-by: Ashesh Vidyut <134911583+absolutelightning@users.noreply.github.com> Co-authored-by: Ganesh S <ganesh.seetharaman@hashicorp.com> Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com>
This commit is contained in:
parent
2133fd40c6
commit
c7e3db2c60
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
catalog api: fixes a bug with catalog api where filter query parameter was not working correctly for the `/v1/catalog/services` endpoint
|
||||||
|
```
|
|
@ -596,7 +596,7 @@ func (c *Catalog) ListServices(args *structs.DCSpecificRequest, reply *structs.I
|
||||||
if len(args.NodeMetaFilters) > 0 {
|
if len(args.NodeMetaFilters) > 0 {
|
||||||
reply.Index, serviceNodes, err = state.ServicesByNodeMeta(ws, args.NodeMetaFilters, &args.EnterpriseMeta, args.PeerName)
|
reply.Index, serviceNodes, err = state.ServicesByNodeMeta(ws, args.NodeMetaFilters, &args.EnterpriseMeta, args.PeerName)
|
||||||
} else {
|
} else {
|
||||||
reply.Index, serviceNodes, err = state.Services(ws, &args.EnterpriseMeta, args.PeerName)
|
reply.Index, serviceNodes, err = state.Services(ws, &args.EnterpriseMeta, args.PeerName, args.Filter != "")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -1218,7 +1218,7 @@ func terminatingGatewayVirtualIPsSupported(tx ReadTxn, ws memdb.WatchSet) (bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Services returns all services along with a list of associated tags.
|
// Services returns all services along with a list of associated tags.
|
||||||
func (s *Store) Services(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string) (uint64, []*structs.ServiceNode, error) {
|
func (s *Store) Services(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerName string, joinServiceNodes bool) (uint64, structs.ServiceNodes, error) {
|
||||||
tx := s.db.Txn(false)
|
tx := s.db.Txn(false)
|
||||||
defer tx.Abort()
|
defer tx.Abort()
|
||||||
|
|
||||||
|
@ -1236,6 +1236,13 @@ func (s *Store) Services(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta, peerNam
|
||||||
for service := services.Next(); service != nil; service = services.Next() {
|
for service := services.Next(); service != nil; service = services.Next() {
|
||||||
result = append(result, service.(*structs.ServiceNode))
|
result = append(result, service.(*structs.ServiceNode))
|
||||||
}
|
}
|
||||||
|
if joinServiceNodes {
|
||||||
|
parsedResult, err := parseServiceNodes(tx, ws, result, entMeta, peerName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("failed querying and parsing services :%s", err)
|
||||||
|
}
|
||||||
|
return idx, parsedResult, nil
|
||||||
|
}
|
||||||
return idx, result, nil
|
return idx, result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1311,6 +1318,7 @@ func (s *Store) ServicesByNodeMeta(ws memdb.WatchSet, filters map[string]string,
|
||||||
EnterpriseMeta: *entMeta,
|
EnterpriseMeta: *entMeta,
|
||||||
PeerName: peerName,
|
PeerName: peerName,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, fmt.Errorf("failed nodes lookup: %s", err)
|
return 0, nil, fmt.Errorf("failed nodes lookup: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -1330,7 +1338,6 @@ func (s *Store) ServicesByNodeMeta(ws memdb.WatchSet, filters map[string]string,
|
||||||
if len(filters) > 1 && !structs.SatisfiesMetaFilters(n.Meta, filters) {
|
if len(filters) > 1 && !structs.SatisfiesMetaFilters(n.Meta, filters) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// List all the services on the node
|
// List all the services on the node
|
||||||
services, err := catalogServiceListByNode(tx, n.Node, entMeta, n.PeerName, false)
|
services, err := catalogServiceListByNode(tx, n.Node, entMeta, n.PeerName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2178,7 +2178,7 @@ func TestStateStore_Services(t *testing.T) {
|
||||||
|
|
||||||
// Listing with no results returns an empty list.
|
// Listing with no results returns an empty list.
|
||||||
ws := memdb.NewWatchSet()
|
ws := memdb.NewWatchSet()
|
||||||
idx, services, err := s.Services(ws, nil, "")
|
idx, services, err := s.Services(ws, nil, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -2223,7 +2223,7 @@ func TestStateStore_Services(t *testing.T) {
|
||||||
|
|
||||||
// Pull all the services.
|
// Pull all the services.
|
||||||
ws = memdb.NewWatchSet()
|
ws = memdb.NewWatchSet()
|
||||||
idx, services, err = s.Services(ws, nil, "")
|
idx, services, err = s.Services(ws, nil, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -2232,7 +2232,7 @@ func TestStateStore_Services(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the result.
|
// Verify the result.
|
||||||
expected := []*structs.ServiceNode{
|
expected := structs.ServiceNodes{
|
||||||
ns1Dogs.ToServiceNode("node1"),
|
ns1Dogs.ToServiceNode("node1"),
|
||||||
ns1.ToServiceNode("node1"),
|
ns1.ToServiceNode("node1"),
|
||||||
ns2.ToServiceNode("node2"),
|
ns2.ToServiceNode("node2"),
|
||||||
|
|
|
@ -220,6 +220,73 @@ func TestAPI_CatalogServices_NodeMetaFilter(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPI_CatalogServices_FilterExpr_NodeMeta(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
meta := map[string]string{"somekey": "somevalue", "synthetic": "true"}
|
||||||
|
c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
|
||||||
|
conf.NodeMeta = meta
|
||||||
|
})
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
catalog := c.Catalog()
|
||||||
|
// Make sure we get the service back when filtering by filter expression
|
||||||
|
retry.Run(t, func(r *retry.R) {
|
||||||
|
services, meta, err := catalog.Services(&QueryOptions{Filter: "NodeMeta[\"synthetic\"] == true and NodeMeta[\"somekey\"] == somevalue"})
|
||||||
|
if err != nil {
|
||||||
|
r.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
r.Fatalf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
if len(services) == 0 {
|
||||||
|
r.Fatalf("Bad: %v", services)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
retry.Run(t, func(r *retry.R) {
|
||||||
|
services, meta, err := catalog.Services(&QueryOptions{Filter: "NodeMeta.synthetic == true"})
|
||||||
|
if err != nil {
|
||||||
|
r.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
r.Fatalf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(services) == 0 {
|
||||||
|
r.Fatalf("Bad: %v", services)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
retry.Run(t, func(r *retry.R) {
|
||||||
|
services, meta, err := catalog.Services(&QueryOptions{Filter: "NodeMeta.somekey == somevalue"})
|
||||||
|
if err != nil {
|
||||||
|
r.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
r.Fatalf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(services) == 0 {
|
||||||
|
r.Fatalf("Bad: %v", services)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
retry.Run(t, func(r *retry.R) {
|
||||||
|
services, meta, err := catalog.Services(&QueryOptions{Filter: "NodeMeta.nope == nope"})
|
||||||
|
if err != nil {
|
||||||
|
r.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
r.Fatalf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(services) != 0 {
|
||||||
|
r.Fatalf("Bad: %v", services)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestAPI_CatalogService(t *testing.T) {
|
func TestAPI_CatalogService(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
c, s := makeClient(t)
|
c, s := makeClient(t)
|
||||||
|
|
Loading…
Reference in New Issue