Add deregister critical service field and refactor duration parsing

This commit is contained in:
Kyle Havlovitz 2017-10-25 19:17:41 -07:00
parent 291455f475
commit ce4e8c46fa
No known key found for this signature in database
GPG Key ID: 8A5E6B173056AD6C
6 changed files with 75 additions and 42 deletions

View File

@ -1407,7 +1407,7 @@ func (a *Agent) reapServicesInternal() {
} }
// reapServices is a long running goroutine that looks for checks that have been // reapServices is a long running goroutine that looks for checks that have been
// critical too long and dregisters their associated services. // critical too long and deregisters their associated services.
func (a *Agent) reapServices() { func (a *Agent) reapServices() {
for { for {
select { select {

View File

@ -8,13 +8,15 @@ import (
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
) )
var durations = NewDurationFixer("interval", "timeout", "deregistercriticalserviceafter")
func (s *HTTPServer) CatalogRegister(resp http.ResponseWriter, req *http.Request) (interface{}, error) { func (s *HTTPServer) CatalogRegister(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
if req.Method != "PUT" { if req.Method != "PUT" {
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}} return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
} }
var args structs.RegisterRequest var args structs.RegisterRequest
if err := decodeBody(req, &args, nil); err != nil { if err := decodeBody(req, &args, durations.FixupDurations); err != nil {
resp.WriteHeader(http.StatusBadRequest) resp.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(resp, "Request decode failed: %v", err) fmt.Fprintf(resp, "Request decode failed: %v", err)
return nil, nil return nil, nil

View File

@ -220,7 +220,8 @@ func (s *HTTPServer) OperatorAutopilotConfiguration(resp http.ResponseWriter, re
s.parseToken(req, &args.Token) s.parseToken(req, &args.Token)
var conf api.AutopilotConfiguration var conf api.AutopilotConfiguration
if err := decodeBody(req, &conf, FixupConfigDurations); err != nil { durations := NewDurationFixer("lastcontactthreshold", "serverstabilizationtime")
if err := decodeBody(req, &conf, durations.FixupDurations); err != nil {
resp.WriteHeader(http.StatusBadRequest) resp.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(resp, "Error parsing autopilot config: %v", err) fmt.Fprintf(resp, "Error parsing autopilot config: %v", err)
return nil, nil return nil, nil
@ -265,16 +266,42 @@ func (s *HTTPServer) OperatorAutopilotConfiguration(resp http.ResponseWriter, re
} }
} }
// FixupConfigDurations is used to handle parsing the duration fields in type durationFixer map[string]struct{}
// the Autopilot config struct
func FixupConfigDurations(raw interface{}) error { func NewDurationFixer(fields ...string) durationFixer {
d := make(map[string]struct{})
for _, field := range fields {
d[field] = struct{}{}
}
return d
}
// FixupDurations is used to handle parsing any field names in the map to time.Durations
func (d durationFixer) FixupDurations(raw interface{}) error {
rawMap, ok := raw.(map[string]interface{}) rawMap, ok := raw.(map[string]interface{})
if !ok { if !ok {
return nil return nil
} }
for key, val := range rawMap { for key, val := range rawMap {
if strings.ToLower(key) == "lastcontactthreshold" || if key == "NodeMeta" {
strings.ToLower(key) == "serverstabilizationtime" { continue
}
switch val.(type) {
case map[string]interface{}:
if err := d.FixupDurations(val); err != nil {
return err
}
case []interface{}:
for _, v := range val.([]interface{}) {
if err := d.FixupDurations(v); err != nil {
return err
}
}
default:
if _, ok := d[strings.ToLower(key)]; ok {
// Convert a string value into an integer // Convert a string value into an integer
if vStr, ok := val.(string); ok { if vStr, ok := val.(string); ok {
dur, err := time.ParseDuration(vStr) dur, err := time.ParseDuration(vStr)
@ -285,6 +312,7 @@ func FixupConfigDurations(raw interface{}) error {
} }
} }
} }
}
return nil return nil
} }

View File

@ -487,8 +487,9 @@ type HealthCheck struct {
Header map[string][]string `json:",omitempty"` Header map[string][]string `json:",omitempty"`
Method string `json:",omitempty"` Method string `json:",omitempty"`
TCP string `json:",omitempty"` TCP string `json:",omitempty"`
Interval string `json:",omitempty"` Interval api.ReadableDuration `json:",omitempty"`
Timeout string `json:",omitempty"` Timeout api.ReadableDuration `json:",omitempty"`
DeregisterCriticalServiceAfter api.ReadableDuration `json:",omitempty"`
RaftIndex RaftIndex
} }

View File

@ -20,8 +20,9 @@ type AgentCheck struct {
Method string Method string
TLSSkipVerify bool TLSSkipVerify bool
TCP string TCP string
Interval string Interval ReadableDuration
Timeout string Timeout ReadableDuration
DeregisterCriticalServiceAfter ReadableDuration
} }
// AgentService represents a service known to the agent // AgentService represents a service known to the agent

View File

@ -40,8 +40,9 @@ type HealthCheck struct {
Method string Method string
TLSSkipVerify bool TLSSkipVerify bool
TCP string TCP string
Interval string Interval ReadableDuration
Timeout string Timeout ReadableDuration
DeregisterCriticalServiceAfter ReadableDuration
} }
// HealthChecks is a collection of HealthCheck structs. // HealthChecks is a collection of HealthCheck structs.