consul/api/prepared_query_test.go

238 lines
5.3 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package api
import (
"reflect"
"testing"
"github.com/hashicorp/consul/sdk/testutil/retry"
)
func TestAPI_PreparedQuery(t *testing.T) {
t.Parallel()
c, s := makeClient(t)
defer s.Stop()
// Set up a node and a service.
reg := &CatalogRegistration{
Datacenter: "dc1",
Node: "foobar",
Address: "192.168.10.10",
TaggedAddresses: map[string]string{
"wan": "127.0.0.1",
},
NodeMeta: map[string]string{"somekey": "somevalue"},
Service: &AgentService{
ID: "redis1",
Service: "redis",
Tags: []string{"primary", "v1"},
Meta: map[string]string{"redis-version": "4.0"},
Port: 8000,
},
}
catalog := c.Catalog()
retry.Run(t, func(r *retry.R) {
if _, err := catalog.Register(reg, nil); err != nil {
r.Fatal(err)
}
if _, _, err := catalog.Node("foobar", nil); err != nil {
r.Fatal(err)
}
})
// Create a simple prepared query.
def := &PreparedQueryDefinition{
Name: "test",
Service: ServiceQuery{
Service: "redis",
NodeMeta: map[string]string{"somekey": "somevalue"},
ServiceMeta: map[string]string{"redis-version": "4.0"},
},
}
query := c.PreparedQuery()
var err error
def.ID, _, err = query.Create(def, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
// Read it back.
defs, _, err := query.Get(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(defs) != 1 || !reflect.DeepEqual(defs[0], def) {
t.Fatalf("bad: %v", defs)
}
// List them all.
defs, _, err = query.List(nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(defs) != 1 || !reflect.DeepEqual(defs[0], def) {
t.Fatalf("bad: %v", defs)
}
// Make an update.
def.Name = "my-query"
_, err = query.Update(def, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
// Read it back again to verify the update worked.
defs, _, err = query.Get(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(defs) != 1 || !reflect.DeepEqual(defs[0], def) {
t.Fatalf("bad: %v", defs)
}
// Execute by ID.
results, _, err := query.Execute(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(results.Nodes) != 1 || results.Nodes[0].Node.Node != "foobar" {
t.Fatalf("bad: %v", results)
}
if wan, ok := results.Nodes[0].Node.TaggedAddresses["wan"]; !ok || wan != "127.0.0.1" {
t.Fatalf("bad: %v", results)
}
// Execute by name.
results, _, err = query.Execute("my-query", nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(results.Nodes) != 1 || results.Nodes[0].Node.Node != "foobar" {
t.Fatalf("bad: %v", results)
}
if wan, ok := results.Nodes[0].Node.TaggedAddresses["wan"]; !ok || wan != "127.0.0.1" {
t.Fatalf("bad: %v", results)
}
if results.Nodes[0].Node.Datacenter != "dc1" {
t.Fatalf("bad datacenter: %v", results)
}
// Add new node with failing health check.
reg2 := reg
reg2.Node = "failingnode"
reg2.Check = &AgentCheck{
Node: "failingnode",
ServiceID: "redis1",
ServiceName: "redis",
Name: "failingcheck",
Status: "critical",
}
retry.Run(t, func(r *retry.R) {
if _, err := catalog.Register(reg2, nil); err != nil {
r.Fatal(err)
}
if _, _, err := catalog.Node("failingnode", nil); err != nil {
r.Fatal(err)
}
})
// Execute by ID. Should return only healthy node.
results, _, err = query.Execute(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(results.Nodes) != 1 || results.Nodes[0].Node.Node != "foobar" {
t.Fatalf("bad: %v", results)
}
if wan, ok := results.Nodes[0].Node.TaggedAddresses["wan"]; !ok || wan != "127.0.0.1" {
t.Fatalf("bad: %v", results)
}
// Update PQ with ignore rule for the failing check
def.Service.IgnoreCheckIDs = []string{"failingcheck"}
_, err = query.Update(def, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
// Execute by ID. Should return BOTH nodes ignoring the failing check.
results, _, err = query.Execute(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(results.Nodes) != 2 {
t.Fatalf("got %d nodes, want 2", len(results.Nodes))
}
// Delete it.
_, err = query.Delete(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
// Make sure there are no longer any queries.
defs, _, err = query.List(nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(defs) != 0 {
t.Fatalf("bad: %v", defs)
}
}
func TestAPI_PreparedQueryRemoveEmptyTags(t *testing.T) {
t.Parallel()
c, s := makeClient(t)
defer s.Stop()
def := &PreparedQueryDefinition{
Name: "test",
Service: ServiceQuery{
Service: "redis",
},
Template: QueryTemplate{
RemoveEmptyTags: false,
},
}
query := c.PreparedQuery()
var err error
def.ID, _, err = query.Create(def, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
queries, _, err := query.Get(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(queries) != 1 {
t.Fatalf("wrong length: %#v", queries)
}
if queries[0].Template.RemoveEmptyTags {
t.Fatalf("wrong value: %v", queries[0].Template.RemoveEmptyTags)
}
def.Template.RemoveEmptyTags = true
_, err = query.Update(def, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
queries, _, err = query.Get(def.ID, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(queries) != 1 {
t.Fatalf("wrong length: %#v", queries)
}
if !queries[0].Template.RemoveEmptyTags {
t.Fatalf("wrong value: %v", queries[0].Template.RemoveEmptyTags)
}
}