Nest restart fields in CheckRestart
This commit is contained in:
parent
bf34505509
commit
b35d208428
53
api/tasks.go
53
api/tasks.go
|
@ -79,36 +79,43 @@ func (r *RestartPolicy) Merge(rp *RestartPolicy) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckRestart describes if and when a task should be restarted based on
|
||||||
|
// failing health checks.
|
||||||
|
type CheckRestart struct {
|
||||||
|
Limit int `mapstructure:"limit"`
|
||||||
|
Grace time.Duration `mapstructure:"grace_period"`
|
||||||
|
OnWarning bool `mapstructure:"on_warning"`
|
||||||
|
}
|
||||||
|
|
||||||
// The ServiceCheck data model represents the consul health check that
|
// The ServiceCheck data model represents the consul health check that
|
||||||
// Nomad registers for a Task
|
// Nomad registers for a Task
|
||||||
type ServiceCheck struct {
|
type ServiceCheck struct {
|
||||||
Id string
|
Id string
|
||||||
Name string
|
Name string
|
||||||
Type string
|
Type string
|
||||||
Command string
|
Command string
|
||||||
Args []string
|
Args []string
|
||||||
Path string
|
Path string
|
||||||
Protocol string
|
Protocol string
|
||||||
PortLabel string `mapstructure:"port"`
|
PortLabel string `mapstructure:"port"`
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
InitialStatus string `mapstructure:"initial_status"`
|
InitialStatus string `mapstructure:"initial_status"`
|
||||||
TLSSkipVerify bool `mapstructure:"tls_skip_verify"`
|
TLSSkipVerify bool `mapstructure:"tls_skip_verify"`
|
||||||
Header map[string][]string
|
Header map[string][]string
|
||||||
Method string
|
Method string
|
||||||
RestartAfter int
|
CheckRestart *CheckRestart `mapstructure:"check_restart"`
|
||||||
RestartGrace time.Duration
|
|
||||||
RestartWarning bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Service model represents a Consul service definition
|
// The Service model represents a Consul service definition
|
||||||
type Service struct {
|
type Service struct {
|
||||||
Id string
|
Id string
|
||||||
Name string
|
Name string
|
||||||
Tags []string
|
Tags []string
|
||||||
PortLabel string `mapstructure:"port"`
|
PortLabel string `mapstructure:"port"`
|
||||||
AddressMode string `mapstructure:"address_mode"`
|
AddressMode string `mapstructure:"address_mode"`
|
||||||
Checks []ServiceCheck
|
Checks []ServiceCheck
|
||||||
|
CheckRestart *CheckRestart `mapstructure:"check_restart"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Canonicalize(t *Task, tg *TaskGroup, job *Job) {
|
func (s *Service) Canonicalize(t *Task, tg *TaskGroup, job *Job) {
|
||||||
|
|
|
@ -685,27 +685,38 @@ func ApiTaskToStructsTask(apiTask *api.Task, structsTask *structs.Task) {
|
||||||
Tags: service.Tags,
|
Tags: service.Tags,
|
||||||
AddressMode: service.AddressMode,
|
AddressMode: service.AddressMode,
|
||||||
}
|
}
|
||||||
|
if service.CheckRestart != nil {
|
||||||
|
structsTask.Services[i].CheckRestart = &structs.CheckRestart{
|
||||||
|
Limit: service.CheckRestart.Limit,
|
||||||
|
Grace: service.CheckRestart.Grace,
|
||||||
|
OnWarning: service.CheckRestart.OnWarning,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if l := len(service.Checks); l != 0 {
|
if l := len(service.Checks); l != 0 {
|
||||||
structsTask.Services[i].Checks = make([]*structs.ServiceCheck, l)
|
structsTask.Services[i].Checks = make([]*structs.ServiceCheck, l)
|
||||||
for j, check := range service.Checks {
|
for j, check := range service.Checks {
|
||||||
structsTask.Services[i].Checks[j] = &structs.ServiceCheck{
|
structsTask.Services[i].Checks[j] = &structs.ServiceCheck{
|
||||||
Name: check.Name,
|
Name: check.Name,
|
||||||
Type: check.Type,
|
Type: check.Type,
|
||||||
Command: check.Command,
|
Command: check.Command,
|
||||||
Args: check.Args,
|
Args: check.Args,
|
||||||
Path: check.Path,
|
Path: check.Path,
|
||||||
Protocol: check.Protocol,
|
Protocol: check.Protocol,
|
||||||
PortLabel: check.PortLabel,
|
PortLabel: check.PortLabel,
|
||||||
Interval: check.Interval,
|
Interval: check.Interval,
|
||||||
Timeout: check.Timeout,
|
Timeout: check.Timeout,
|
||||||
InitialStatus: check.InitialStatus,
|
InitialStatus: check.InitialStatus,
|
||||||
TLSSkipVerify: check.TLSSkipVerify,
|
TLSSkipVerify: check.TLSSkipVerify,
|
||||||
Header: check.Header,
|
Header: check.Header,
|
||||||
Method: check.Method,
|
Method: check.Method,
|
||||||
RestartAfter: check.RestartAfter,
|
}
|
||||||
RestartGrace: check.RestartGrace,
|
if check.CheckRestart != nil {
|
||||||
RestartWarning: check.RestartWarning,
|
structsTask.Services[i].Checks[j].CheckRestart = &structs.CheckRestart{
|
||||||
|
Limit: check.CheckRestart.Limit,
|
||||||
|
Grace: check.CheckRestart.Grace,
|
||||||
|
OnWarning: check.CheckRestart.OnWarning,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2757,6 +2757,70 @@ func (tg *TaskGroup) GoString() string {
|
||||||
return fmt.Sprintf("*%#v", *tg)
|
return fmt.Sprintf("*%#v", *tg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckRestart describes if and when a task should be restarted based on
|
||||||
|
// failing health checks.
|
||||||
|
type CheckRestart struct {
|
||||||
|
Limit int // Restart task after this many unhealthy intervals
|
||||||
|
Grace time.Duration // Grace time to give tasks after starting to get healthy
|
||||||
|
OnWarning bool // If true treat checks in `warning` as unhealthy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CheckRestart) Copy() *CheckRestart {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nc := new(CheckRestart)
|
||||||
|
*nc = *c
|
||||||
|
return nc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge non-zero values from other CheckRestart into a copy of this
|
||||||
|
// CheckRestart. Returns nil iff both are nil.
|
||||||
|
func (c *CheckRestart) Merge(o *CheckRestart) *CheckRestart {
|
||||||
|
if c == nil {
|
||||||
|
// Just return other
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
nc := c.Copy()
|
||||||
|
|
||||||
|
if o == nil {
|
||||||
|
// Nothing to merge
|
||||||
|
return nc.Copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
if nc.Limit == 0 {
|
||||||
|
nc.Limit = o.Limit
|
||||||
|
}
|
||||||
|
|
||||||
|
if nc.Grace == 0 {
|
||||||
|
nc.Grace = o.Grace
|
||||||
|
}
|
||||||
|
|
||||||
|
if !nc.OnWarning {
|
||||||
|
nc.OnWarning = o.OnWarning
|
||||||
|
}
|
||||||
|
|
||||||
|
return nc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CheckRestart) Validate() error {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Limit < 0 {
|
||||||
|
return fmt.Errorf("limit must be greater than or equal to 0 but found %d", c.Limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Grace < 0 {
|
||||||
|
return fmt.Errorf("grace period must be greater than or equal to 0 but found %d", c.Grace)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ServiceCheckHTTP = "http"
|
ServiceCheckHTTP = "http"
|
||||||
ServiceCheckTCP = "tcp"
|
ServiceCheckTCP = "tcp"
|
||||||
|
@ -2775,22 +2839,20 @@ const (
|
||||||
// The ServiceCheck data model represents the consul health check that
|
// The ServiceCheck data model represents the consul health check that
|
||||||
// Nomad registers for a Task
|
// Nomad registers for a Task
|
||||||
type ServiceCheck struct {
|
type ServiceCheck struct {
|
||||||
Name string // Name of the check, defaults to id
|
Name string // Name of the check, defaults to id
|
||||||
Type string // Type of the check - tcp, http, docker and script
|
Type string // Type of the check - tcp, http, docker and script
|
||||||
Command string // Command is the command to run for script checks
|
Command string // Command is the command to run for script checks
|
||||||
Args []string // Args is a list of argumes for script checks
|
Args []string // Args is a list of argumes for script checks
|
||||||
Path string // path of the health check url for http type check
|
Path string // path of the health check url for http type check
|
||||||
Protocol string // Protocol to use if check is http, defaults to http
|
Protocol string // Protocol to use if check is http, defaults to http
|
||||||
PortLabel string // The port to use for tcp/http checks
|
PortLabel string // The port to use for tcp/http checks
|
||||||
Interval time.Duration // Interval of the check
|
Interval time.Duration // Interval of the check
|
||||||
Timeout time.Duration // Timeout of the response from the check before consul fails the check
|
Timeout time.Duration // Timeout of the response from the check before consul fails the check
|
||||||
InitialStatus string // Initial status of the check
|
InitialStatus string // Initial status of the check
|
||||||
TLSSkipVerify bool // Skip TLS verification when Protocol=https
|
TLSSkipVerify bool // Skip TLS verification when Protocol=https
|
||||||
Method string // HTTP Method to use (GET by default)
|
Method string // HTTP Method to use (GET by default)
|
||||||
Header map[string][]string // HTTP Headers for Consul to set when making HTTP checks
|
Header map[string][]string // HTTP Headers for Consul to set when making HTTP checks
|
||||||
RestartAfter int // Restart task after this many unhealthy intervals
|
CheckRestart *CheckRestart // If and when a task should be restarted based on checks
|
||||||
RestartGrace time.Duration // Grace time to give tasks after starting to get healthy
|
|
||||||
RestartWarning bool // If true treat checks in `warning` as unhealthy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *ServiceCheck) Copy() *ServiceCheck {
|
func (sc *ServiceCheck) Copy() *ServiceCheck {
|
||||||
|
@ -2801,6 +2863,7 @@ func (sc *ServiceCheck) Copy() *ServiceCheck {
|
||||||
*nsc = *sc
|
*nsc = *sc
|
||||||
nsc.Args = helper.CopySliceString(sc.Args)
|
nsc.Args = helper.CopySliceString(sc.Args)
|
||||||
nsc.Header = helper.CopyMapStringSliceString(sc.Header)
|
nsc.Header = helper.CopyMapStringSliceString(sc.Header)
|
||||||
|
nsc.CheckRestart = sc.CheckRestart.Copy()
|
||||||
return nsc
|
return nsc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2866,7 +2929,7 @@ func (sc *ServiceCheck) validate() error {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return sc.CheckRestart.Validate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiresPort returns whether the service check requires the task has a port.
|
// RequiresPort returns whether the service check requires the task has a port.
|
||||||
|
@ -2939,6 +3002,9 @@ type Service struct {
|
||||||
|
|
||||||
Tags []string // List of tags for the service
|
Tags []string // List of tags for the service
|
||||||
Checks []*ServiceCheck // List of checks associated with the service
|
Checks []*ServiceCheck // List of checks associated with the service
|
||||||
|
|
||||||
|
// CheckRestart will be propagated to Checks if set.
|
||||||
|
CheckRestart *CheckRestart
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Copy() *Service {
|
func (s *Service) Copy() *Service {
|
||||||
|
@ -2948,6 +3014,7 @@ func (s *Service) Copy() *Service {
|
||||||
ns := new(Service)
|
ns := new(Service)
|
||||||
*ns = *s
|
*ns = *s
|
||||||
ns.Tags = helper.CopySliceString(ns.Tags)
|
ns.Tags = helper.CopySliceString(ns.Tags)
|
||||||
|
ns.CheckRestart = s.CheckRestart.Copy()
|
||||||
|
|
||||||
if s.Checks != nil {
|
if s.Checks != nil {
|
||||||
checks := make([]*ServiceCheck, len(ns.Checks))
|
checks := make([]*ServiceCheck, len(ns.Checks))
|
||||||
|
@ -2983,6 +3050,14 @@ func (s *Service) Canonicalize(job string, taskGroup string, task string) {
|
||||||
for _, check := range s.Checks {
|
for _, check := range s.Checks {
|
||||||
check.Canonicalize(s.Name)
|
check.Canonicalize(s.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If CheckRestart is set propagate it to checks
|
||||||
|
if s.CheckRestart != nil {
|
||||||
|
for _, check := range s.Checks {
|
||||||
|
// Merge Service CheckRestart into Check's so Check's takes precedence
|
||||||
|
check.CheckRestart = check.CheckRestart.Merge(s.CheckRestart)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the Check definition is valid
|
// Validate checks if the Check definition is valid
|
||||||
|
@ -3016,6 +3091,11 @@ func (s *Service) Validate() error {
|
||||||
mErr.Errors = append(mErr.Errors, fmt.Errorf("check %s invalid: %v", c.Name, err))
|
mErr.Errors = append(mErr.Errors, fmt.Errorf("check %s invalid: %v", c.Name, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.CheckRestart != nil && len(s.Checks) == 0 {
|
||||||
|
mErr.Errors = append(mErr.Errors, fmt.Errorf("check_restart specified but no checks"))
|
||||||
|
}
|
||||||
|
|
||||||
return mErr.ErrorOrNil()
|
return mErr.ErrorOrNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue