Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store check type in catalog #6561

Merged
merged 6 commits into from
Oct 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -2268,6 +2268,7 @@ func (a *Agent) addServiceInternal(req *addServiceRequest) error {
ServiceID: service.ID,
ServiceName: service.Service,
ServiceTags: service.Tags,
Type: chkType.Type(),
}
if chkType.Status != "" {
check.Status = chkType.Status
Expand Down Expand Up @@ -3613,6 +3614,7 @@ func (a *Agent) EnableServiceMaintenance(serviceID, reason, token string) error
ServiceID: service.ID,
ServiceName: service.Service,
Status: api.HealthCritical,
Type: "maintenance",
}
a.AddCheck(check, nil, true, token, ConfigSourceLocal)
a.logger.Printf("[INFO] agent: Service %q entered maintenance mode", serviceID)
Expand Down Expand Up @@ -3659,6 +3661,7 @@ func (a *Agent) EnableNodeMaintenance(reason, token string) {
Name: "Node Maintenance Mode",
Notes: reason,
Status: api.HealthCritical,
Type: "maintenance",
}
a.AddCheck(check, nil, true, token, ConfigSourceLocal)
a.logger.Printf("[INFO] agent: Node entered maintenance mode")
Expand Down
3 changes: 3 additions & 0 deletions agent/agent_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,9 @@ func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Requ
return nil, nil
}

// Store the type of check based on the definition
health.Type = chkType.Type()

if health.ServiceID != "" {
// fixup the service name so that vetCheckRegister requires the right ACLs
service := s.agent.State.Service(health.ServiceID)
Expand Down
10 changes: 10 additions & 0 deletions agent/agent_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2429,6 +2429,11 @@ func testAgent_RegisterService(t *testing.T, extraHCL string) {
if len(checks) != 3 {
t.Fatalf("bad: %v", checks)
}
for _, c := range checks {
if c.Type != "ttl" {
t.Fatalf("expected ttl check type, got %s", c.Type)
}
}

if len(a.checkTTLs) != 3 {
t.Fatalf("missing test check ttls: %v", a.checkTTLs)
Expand Down Expand Up @@ -4066,6 +4071,11 @@ func TestAgent_RegisterCheck_Service(t *testing.T) {
if result["memcache_check2"].ServiceID != "memcache" {
t.Fatalf("bad: %#v", result["memcached_check2"])
}

// Make sure the new check has the right type
if result["memcache_check2"].Type != "ttl" {
t.Fatalf("expected TTL type, got %s", result["memcache_check2"].Type)
}
}

func TestAgent_Monitor(t *testing.T) {
Expand Down
24 changes: 22 additions & 2 deletions agent/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ func testAgent_AddService(t *testing.T, extraHCL string) {
ServiceID: "svcid1",
ServiceName: "svcname1",
ServiceTags: []string{"tag1"},
Type: "ttl",
},
},
},
Expand Down Expand Up @@ -438,6 +439,7 @@ func testAgent_AddService(t *testing.T, extraHCL string) {
ServiceID: "svcid2",
ServiceName: "svcname2",
ServiceTags: []string{"tag2"},
Type: "ttl",
},
"check-noname": &structs.HealthCheck{
Node: "node1",
Expand All @@ -447,6 +449,7 @@ func testAgent_AddService(t *testing.T, extraHCL string) {
ServiceID: "svcid2",
ServiceName: "svcname2",
ServiceTags: []string{"tag2"},
Type: "ttl",
},
"service:svcid2:3": &structs.HealthCheck{
Node: "node1",
Expand All @@ -456,6 +459,7 @@ func testAgent_AddService(t *testing.T, extraHCL string) {
ServiceID: "svcid2",
ServiceName: "svcname2",
ServiceTags: []string{"tag2"},
Type: "ttl",
},
"service:svcid2:4": &structs.HealthCheck{
Node: "node1",
Expand All @@ -465,6 +469,7 @@ func testAgent_AddService(t *testing.T, extraHCL string) {
ServiceID: "svcid2",
ServiceName: "svcname2",
ServiceTags: []string{"tag2"},
Type: "ttl",
},
},
},
Expand Down Expand Up @@ -828,8 +833,23 @@ func testAgent_RemoveServiceRemovesAllChecks(t *testing.T, extraHCL string) {
svc := &structs.NodeService{ID: "redis", Service: "redis", Port: 8000}
chk1 := &structs.CheckType{CheckID: "chk1", Name: "chk1", TTL: time.Minute}
chk2 := &structs.CheckType{CheckID: "chk2", Name: "chk2", TTL: 2 * time.Minute}
hchk1 := &structs.HealthCheck{Node: "node1", CheckID: "chk1", Name: "chk1", Status: "critical", ServiceID: "redis", ServiceName: "redis"}
hchk2 := &structs.HealthCheck{Node: "node1", CheckID: "chk2", Name: "chk2", Status: "critical", ServiceID: "redis", ServiceName: "redis"}
hchk1 := &structs.HealthCheck{
Node: "node1",
CheckID: "chk1",
Name: "chk1",
Status: "critical",
ServiceID: "redis",
ServiceName: "redis",
Type: "ttl",
}
hchk2 := &structs.HealthCheck{Node: "node1",
CheckID: "chk2",
Name: "chk2",
Status: "critical",
ServiceID: "redis",
ServiceName: "redis",
Type: "ttl",
}

// register service with chk1
if err := a.AddService(svc, []*structs.CheckType{chk1}, false, "", ConfigSourceLocal); err != nil {
Expand Down
53 changes: 53 additions & 0 deletions agent/catalog_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,59 @@ func TestCatalogServices_NodeMetaFilter(t *testing.T) {
}
}

func TestCatalogRegister_checkRegistration(t *testing.T) {
t.Parallel()
a := NewTestAgent(t, t.Name(), "")
defer a.Shutdown()

// Register node with a service and check
check := structs.HealthCheck{
Node: "foo",
CheckID: "foo-check",
Name: "foo check",
ServiceID: "api",
Definition: structs.HealthCheckDefinition{
TCP: "localhost:8888",
Interval: 5 * time.Second,
},
}

args := &structs.RegisterRequest{
Datacenter: "dc1",
Node: "foo",
Address: "127.0.0.1",
Service: &structs.NodeService{
Service: "api",
},
Check: &check,
}

var out struct{}
if err := a.RPC("Catalog.Register", args, &out); err != nil {
t.Fatalf("err: %v", err)
}

retry.Run(t, func(r *retry.R) {
req, _ := http.NewRequest("GET", "/v1/health/checks/api", nil)
resp := httptest.NewRecorder()
obj, err := a.srv.HealthServiceChecks(resp, req)
if err != nil {
r.Fatalf("err: %v", err)
}

checks := obj.(structs.HealthChecks)
if len(checks) != 1 {
r.Fatalf("expected 1 check, got: %d", len(checks))
}
if checks[0].CheckID != check.CheckID {
r.Fatalf("expected check id %s, got %s", check.Type, checks[0].Type)
}
if checks[0].Type != "tcp" {
r.Fatalf("expected check type tcp, got %s", checks[0].Type)
}
})
}

func TestCatalogServiceNodes(t *testing.T) {
t.Parallel()
a := NewTestAgent(t, t.Name(), "")
Expand Down
7 changes: 7 additions & 0 deletions agent/consul/catalog_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ func (c *Catalog) Register(args *structs.RegisterRequest, reply *struct{}) error
check.Node = args.Node
}
checkPreApply(check)

// Populate check type for cases when a check is registered in the catalog directly
// and not via anti-entropy
if check.Type == "" {
chkType := check.CheckType()
check.Type = chkType.Type()
}
}

// Check the complete register request against the given ACL policy.
Expand Down
57 changes: 57 additions & 0 deletions agent/health_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ func TestHealthServiceChecks(t *testing.T) {
Node: a.Config.NodeName,
Name: "consul check",
ServiceID: "consul",
Type: "grpc",
},
}

Expand All @@ -357,6 +358,9 @@ func TestHealthServiceChecks(t *testing.T) {
if len(nodes) != 1 {
t.Fatalf("bad: %v", obj)
}
if nodes[0].Type != "grpc" {
t.Fatalf("expected grpc check type, got %s", nodes[0].Type)
}
}

func TestHealthServiceChecks_NodeMetaFilter(t *testing.T) {
Expand Down Expand Up @@ -970,6 +974,59 @@ func TestHealthServiceNodes_PassingFilter(t *testing.T) {
})
}

func TestHealthServiceNodes_CheckType(t *testing.T) {
t.Parallel()
a := NewTestAgent(t, t.Name(), "")
defer a.Shutdown()
testrpc.WaitForLeader(t, a.RPC, "dc1")

req, _ := http.NewRequest("GET", "/v1/health/service/consul?dc=dc1", nil)
resp := httptest.NewRecorder()
obj, err := a.srv.HealthServiceNodes(resp, req)
require.NoError(t, err)
assertIndex(t, resp)

// Should be 1 health check for consul
nodes := obj.(structs.CheckServiceNodes)
if len(nodes) != 1 {
t.Fatalf("expected 1 node, got %d", len(nodes))
}

args := &structs.RegisterRequest{
Datacenter: "dc1",
Node: a.Config.NodeName,
Address: "127.0.0.1",
NodeMeta: map[string]string{"somekey": "somevalue"},
Check: &structs.HealthCheck{
Node: a.Config.NodeName,
Name: "consul check",
ServiceID: "consul",
Type: "grpc",
},
}

var out struct{}
require.NoError(t, a.RPC("Catalog.Register", args, &out))

req, _ = http.NewRequest("GET", "/v1/health/service/consul?dc=dc1", nil)
resp = httptest.NewRecorder()
obj, err = a.srv.HealthServiceNodes(resp, req)
require.NoError(t, err)

assertIndex(t, resp)

// Should be a non-nil empty list for checks
nodes = obj.(structs.CheckServiceNodes)
require.Len(t, nodes, 1)
require.Len(t, nodes[0].Checks, 2)

for _, check := range nodes[0].Checks {
if check.Name == "consul check" && check.Type != "grpc" {
t.Fatalf("exptected grpc check type, got %s", check.Type)
}
}
}

func TestHealthServiceNodes_WanTranslation(t *testing.T) {
t.Parallel()
a1 := NewTestAgent(t, t.Name(), `
Expand Down
21 changes: 21 additions & 0 deletions agent/structs/check_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,24 @@ func (c *CheckType) IsDocker() bool {
func (c *CheckType) IsGRPC() bool {
return c.GRPC != "" && c.Interval > 0
}

func (c *CheckType) Type() string {
switch {
case c.IsGRPC():
return "grpc"
case c.IsHTTP():
return "http"
case c.IsTTL():
return "ttl"
case c.IsTCP():
return "tcp"
case c.IsAlias():
return "alias"
case c.IsDocker():
return "docker"
case c.IsScript():
return "script"
default:
return ""
}
}
27 changes: 27 additions & 0 deletions agent/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,7 @@ type HealthCheck struct {
ServiceID string // optional associated service
ServiceName string // optional service name
ServiceTags []string // optional service tags
Type string // Check type: http/ttl/tcp/etc

Definition HealthCheckDefinition `bexpr:"-"`

Expand Down Expand Up @@ -1254,6 +1255,32 @@ func (c *HealthCheck) Clone() *HealthCheck {
return clone
}

func (c *HealthCheck) CheckType() *CheckType {
return &CheckType{
CheckID: c.CheckID,
Name: c.Name,
Status: c.Status,
Notes: c.Notes,

ScriptArgs: c.Definition.ScriptArgs,
AliasNode: c.Definition.AliasNode,
AliasService: c.Definition.AliasService,
HTTP: c.Definition.HTTP,
GRPC: c.Definition.GRPC,
GRPCUseTLS: c.Definition.GRPCUseTLS,
Header: c.Definition.Header,
Method: c.Definition.Method,
TCP: c.Definition.TCP,
Interval: c.Definition.Interval,
DockerContainerID: c.Definition.DockerContainerID,
Shell: c.Definition.Shell,
TLSSkipVerify: c.Definition.TLSSkipVerify,
Timeout: c.Definition.Timeout,
TTL: c.Definition.TTL,
DeregisterCriticalServiceAfter: c.Definition.DeregisterCriticalServiceAfter,
}
}

// HealthChecks is a collection of HealthCheck structs.
type HealthChecks []*HealthCheck

Expand Down
5 changes: 5 additions & 0 deletions agent/structs/structs_filtering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,11 @@ var expectedFieldConfigHealthCheck bexpr.FieldConfigurations = bexpr.FieldConfig
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchIsEmpty, bexpr.MatchIsNotEmpty, bexpr.MatchIn, bexpr.MatchNotIn},
StructFieldName: "ServiceTags",
},
"Type": &bexpr.FieldConfiguration{
CoerceFn: bexpr.CoerceString,
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
StructFieldName: "Type",
},
}

var expectedFieldConfigCheckServiceNode bexpr.FieldConfigurations = bexpr.FieldConfigurations{
Expand Down
1 change: 1 addition & 0 deletions api/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type AgentCheck struct {
Output string
ServiceID string
ServiceName string
Type string
Definition HealthCheckDefinition
}

Expand Down
Loading