mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
api: Add Notes field to service checks (#22397)
Co-authored-by: Piotr Kazmierczak <470696+pkazmierczak@users.noreply.github.com>
This commit is contained in:
3
.changelog/22397.txt
Normal file
3
.changelog/22397.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
```release-note:improvement
|
||||
api: Add support for setting Notes field for Consul health checks
|
||||
```
|
||||
@@ -212,6 +212,7 @@ type ServiceCheck struct {
|
||||
Interval time.Duration `hcl:"interval,optional"`
|
||||
Timeout time.Duration `hcl:"timeout,optional"`
|
||||
InitialStatus string `mapstructure:"initial_status" hcl:"initial_status,optional"`
|
||||
Notes string `hcl:"notes,optional"`
|
||||
TLSServerName string `mapstructure:"tls_server_name" hcl:"tls_server_name,optional"`
|
||||
TLSSkipVerify bool `mapstructure:"tls_skip_verify" hcl:"tls_skip_verify,optional"`
|
||||
Header map[string][]string `hcl:"header,block"`
|
||||
|
||||
@@ -45,6 +45,7 @@ func InterpolateService(taskEnv *TaskEnv, origService *structs.Service) *structs
|
||||
check.Protocol = taskEnv.ReplaceEnv(check.Protocol)
|
||||
check.PortLabel = taskEnv.ReplaceEnv(check.PortLabel)
|
||||
check.InitialStatus = taskEnv.ReplaceEnv(check.InitialStatus)
|
||||
check.Notes = taskEnv.ReplaceEnv(check.Notes)
|
||||
check.Method = taskEnv.ReplaceEnv(check.Method)
|
||||
check.GRPCService = taskEnv.ReplaceEnv(check.GRPCService)
|
||||
check.Header = interpolateMapStringSliceString(taskEnv, check.Header)
|
||||
|
||||
@@ -43,6 +43,7 @@ func TestInterpolateServices(t *testing.T) {
|
||||
Protocol: "${checkproto}",
|
||||
PortLabel: "${checklabel}",
|
||||
InitialStatus: "${checkstatus}",
|
||||
Notes: "${checknotes}",
|
||||
Method: "${checkmethod}",
|
||||
Header: map[string][]string{
|
||||
"${checkheaderk}": {"${checkheaderv}"},
|
||||
@@ -71,6 +72,7 @@ func TestInterpolateServices(t *testing.T) {
|
||||
"checkproto": "checkproto",
|
||||
"checklabel": "checklabel",
|
||||
"checkstatus": "checkstatus",
|
||||
"checknotes": "checknotes",
|
||||
"checkmethod": "checkmethod",
|
||||
"checkheaderk": "checkheaderk",
|
||||
"checkheaderv": "checkheaderv",
|
||||
@@ -104,6 +106,7 @@ func TestInterpolateServices(t *testing.T) {
|
||||
Protocol: "checkproto",
|
||||
PortLabel: "checklabel",
|
||||
InitialStatus: "checkstatus",
|
||||
Notes: "checknotes",
|
||||
Method: "checkmethod",
|
||||
Header: map[string][]string{
|
||||
"checkheaderk": {"checkheaderv"},
|
||||
|
||||
@@ -1624,6 +1624,7 @@ func ApiServicesToStructs(in []*api.Service, group bool) []*structs.Service {
|
||||
Interval: check.Interval,
|
||||
Timeout: check.Timeout,
|
||||
InitialStatus: check.InitialStatus,
|
||||
Notes: check.Notes,
|
||||
TLSServerName: check.TLSServerName,
|
||||
TLSSkipVerify: check.TLSSkipVerify,
|
||||
Header: check.Header,
|
||||
|
||||
@@ -2729,6 +2729,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||
Interval: 4 * time.Second,
|
||||
Timeout: 2 * time.Second,
|
||||
InitialStatus: "ok",
|
||||
Notes: "this is a check",
|
||||
CheckRestart: &api.CheckRestart{
|
||||
Limit: 3,
|
||||
IgnoreWarnings: true,
|
||||
@@ -2838,6 +2839,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||
Interval: 4 * time.Second,
|
||||
Timeout: 2 * time.Second,
|
||||
InitialStatus: "ok",
|
||||
Notes: "this is a check",
|
||||
SuccessBeforePassing: 3,
|
||||
FailuresBeforeCritical: 4,
|
||||
FailuresBeforeWarning: 2,
|
||||
@@ -3163,6 +3165,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||
Interval: 4 * time.Second,
|
||||
Timeout: 2 * time.Second,
|
||||
InitialStatus: "ok",
|
||||
Notes: "this is a check",
|
||||
CheckRestart: &structs.CheckRestart{
|
||||
Grace: 11 * time.Second,
|
||||
Limit: 3,
|
||||
@@ -3274,6 +3277,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||
Interval: 4 * time.Second,
|
||||
Timeout: 2 * time.Second,
|
||||
InitialStatus: "ok",
|
||||
Notes: "this is a check",
|
||||
GRPCService: "foo.Bar",
|
||||
GRPCUseTLS: true,
|
||||
SuccessBeforePassing: 3,
|
||||
|
||||
@@ -1224,6 +1224,7 @@ func parseChecks(service *api.Service, checkObjs *ast.ObjectList) error {
|
||||
"command",
|
||||
"args",
|
||||
"initial_status",
|
||||
"notes",
|
||||
"tls_skip_verify",
|
||||
"header",
|
||||
"method",
|
||||
|
||||
@@ -3838,6 +3838,12 @@ func TestTaskGroupDiff(t *testing.T) {
|
||||
Old: "foo",
|
||||
New: "foo",
|
||||
},
|
||||
{
|
||||
Type: DiffTypeNone,
|
||||
Name: "Notes",
|
||||
Old: "",
|
||||
New: "",
|
||||
},
|
||||
{
|
||||
Type: DiffTypeNone,
|
||||
Name: "OnUpdate",
|
||||
@@ -7607,6 +7613,7 @@ func TestTaskDiff(t *testing.T) {
|
||||
Interval: 1 * time.Second,
|
||||
Timeout: 1 * time.Second,
|
||||
InitialStatus: "critical",
|
||||
Notes: "a note",
|
||||
Header: map[string][]string{
|
||||
"Foo": {"bar"},
|
||||
},
|
||||
@@ -7635,6 +7642,7 @@ func TestTaskDiff(t *testing.T) {
|
||||
Interval: 1 * time.Second,
|
||||
Timeout: 1 * time.Second,
|
||||
InitialStatus: "passing",
|
||||
Notes: "another note",
|
||||
Method: "POST",
|
||||
Header: map[string][]string{
|
||||
"Foo": {"bar", "baz"},
|
||||
@@ -7788,6 +7796,12 @@ func TestTaskDiff(t *testing.T) {
|
||||
Old: "foo",
|
||||
New: "foo",
|
||||
},
|
||||
{
|
||||
Type: DiffTypeEdited,
|
||||
Name: "Notes",
|
||||
Old: "a note",
|
||||
New: "another note",
|
||||
},
|
||||
{
|
||||
Type: DiffTypeEdited,
|
||||
Name: "OnUpdate",
|
||||
|
||||
@@ -68,6 +68,7 @@ type ServiceCheck struct {
|
||||
Interval time.Duration // Interval of the check
|
||||
Timeout time.Duration // Timeout of the response from the check before consul fails the check
|
||||
InitialStatus string // Initial status of the check
|
||||
Notes string // Specifies arbitrary information for humans. This is not used by Consul internally
|
||||
TLSServerName string // ServerName to use for SNI and TLS verification when (Type=https and Protocol=https) or (Type=grpc and GRPCUseTLS=true)
|
||||
TLSSkipVerify bool // Skip TLS verification when (type=https and Protocol=https) or (type=grpc and grpc_use_tls=true)
|
||||
Method string // HTTP Method to use (GET by default)
|
||||
@@ -161,6 +162,10 @@ func (sc *ServiceCheck) Equal(o *ServiceCheck) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if sc.Notes != o.Notes {
|
||||
return false
|
||||
}
|
||||
|
||||
if sc.Interval != o.Interval {
|
||||
return false
|
||||
}
|
||||
@@ -454,6 +459,11 @@ func (sc *ServiceCheck) validateConsul() error {
|
||||
return fmt.Errorf("failures_before_warning not supported for check of type %q", sc.Type)
|
||||
}
|
||||
|
||||
// Arbitrary value, we could bump it if needed
|
||||
if len(sc.Notes) > 255 {
|
||||
return fmt.Errorf("notes must not be longer than 255 characters")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -492,6 +502,7 @@ func (sc *ServiceCheck) Hash(serviceID string) string {
|
||||
hashString(h, sc.Method)
|
||||
hashString(h, sc.Body)
|
||||
hashString(h, sc.OnUpdate)
|
||||
hashString(h, sc.Notes)
|
||||
|
||||
// use name "true" to maintain ID stability
|
||||
hashBool(h, sc.TLSSkipVerify, "true")
|
||||
|
||||
@@ -5,6 +5,7 @@ package structs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -1992,6 +1993,26 @@ func TestService_Validate(t *testing.T) {
|
||||
},
|
||||
expErr: false,
|
||||
},
|
||||
{
|
||||
name: "provider consul with notes too long",
|
||||
input: &Service{
|
||||
Name: "testservice",
|
||||
Provider: "consul",
|
||||
PortLabel: "port",
|
||||
Checks: []*ServiceCheck{
|
||||
{
|
||||
Name: "servicecheck",
|
||||
Type: "http",
|
||||
Path: "/",
|
||||
Interval: 1 * time.Second,
|
||||
Timeout: 3 * time.Second,
|
||||
Notes: strings.Repeat("A", 256),
|
||||
},
|
||||
},
|
||||
},
|
||||
expErr: true,
|
||||
expErrStr: "notes must not be longer than 255 characters",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
Reference in New Issue
Block a user