1package api
2
3import (
4	"fmt"
5	"time"
6)
7
8// CheckRestart describes if and when a task should be restarted based on
9// failing health checks.
10type CheckRestart struct {
11	Limit          int            `mapstructure:"limit"`
12	Grace          *time.Duration `mapstructure:"grace"`
13	IgnoreWarnings bool           `mapstructure:"ignore_warnings"`
14}
15
16// Canonicalize CheckRestart fields if not nil.
17func (c *CheckRestart) Canonicalize() {
18	if c == nil {
19		return
20	}
21
22	if c.Grace == nil {
23		c.Grace = timeToPtr(1 * time.Second)
24	}
25}
26
27// Copy returns a copy of CheckRestart or nil if unset.
28func (c *CheckRestart) Copy() *CheckRestart {
29	if c == nil {
30		return nil
31	}
32
33	nc := new(CheckRestart)
34	nc.Limit = c.Limit
35	if c.Grace != nil {
36		g := *c.Grace
37		nc.Grace = &g
38	}
39	nc.IgnoreWarnings = c.IgnoreWarnings
40	return nc
41}
42
43// Merge values from other CheckRestart over default values on this
44// CheckRestart and return merged copy.
45func (c *CheckRestart) Merge(o *CheckRestart) *CheckRestart {
46	if c == nil {
47		// Just return other
48		return o
49	}
50
51	nc := c.Copy()
52
53	if o == nil {
54		// Nothing to merge
55		return nc
56	}
57
58	if o.Limit > 0 {
59		nc.Limit = o.Limit
60	}
61
62	if o.Grace != nil {
63		nc.Grace = o.Grace
64	}
65
66	if o.IgnoreWarnings {
67		nc.IgnoreWarnings = o.IgnoreWarnings
68	}
69
70	return nc
71}
72
73// ServiceCheck represents the consul health check that Nomad registers.
74type ServiceCheck struct {
75	//FIXME Id is unused. Remove?
76	Id            string
77	Name          string
78	Type          string
79	Command       string
80	Args          []string
81	Path          string
82	Protocol      string
83	PortLabel     string `mapstructure:"port"`
84	AddressMode   string `mapstructure:"address_mode"`
85	Interval      time.Duration
86	Timeout       time.Duration
87	InitialStatus string `mapstructure:"initial_status"`
88	TLSSkipVerify bool   `mapstructure:"tls_skip_verify"`
89	Header        map[string][]string
90	Method        string
91	CheckRestart  *CheckRestart `mapstructure:"check_restart"`
92	GRPCService   string        `mapstructure:"grpc_service"`
93	GRPCUseTLS    bool          `mapstructure:"grpc_use_tls"`
94	TaskName      string        `mapstructure:"task"`
95}
96
97// Service represents a Consul service definition.
98type Service struct {
99	//FIXME Id is unused. Remove?
100	Id           string
101	Name         string
102	Tags         []string
103	CanaryTags   []string `mapstructure:"canary_tags"`
104	PortLabel    string   `mapstructure:"port"`
105	AddressMode  string   `mapstructure:"address_mode"`
106	Checks       []ServiceCheck
107	CheckRestart *CheckRestart `mapstructure:"check_restart"`
108	Connect      *ConsulConnect
109	Meta         map[string]string
110}
111
112// Canonicalize the Service by ensuring its name and address mode are set. Task
113// will be nil for group services.
114func (s *Service) Canonicalize(t *Task, tg *TaskGroup, job *Job) {
115	if s.Name == "" {
116		if t != nil {
117			s.Name = fmt.Sprintf("%s-%s-%s", *job.Name, *tg.Name, t.Name)
118		} else {
119			s.Name = fmt.Sprintf("%s-%s", *job.Name, *tg.Name)
120		}
121	}
122
123	// Default to AddressModeAuto
124	if s.AddressMode == "" {
125		s.AddressMode = "auto"
126	}
127
128	// Canonicalize CheckRestart on Checks and merge Service.CheckRestart
129	// into each check.
130	for i, check := range s.Checks {
131		s.Checks[i].CheckRestart = s.CheckRestart.Merge(check.CheckRestart)
132		s.Checks[i].CheckRestart.Canonicalize()
133	}
134}
135
136// ConsulConnect represents a Consul Connect jobspec stanza.
137type ConsulConnect struct {
138	Native         bool
139	SidecarService *ConsulSidecarService `mapstructure:"sidecar_service"`
140	SidecarTask    *SidecarTask          `mapstructure:"sidecar_task"`
141}
142
143// ConsulSidecarService represents a Consul Connect SidecarService jobspec
144// stanza.
145type ConsulSidecarService struct {
146	Tags  []string
147	Port  string
148	Proxy *ConsulProxy
149}
150
151// SidecarTask represents a subset of Task fields that can be set to override
152// the fields of the Task generated for the sidecar
153type SidecarTask struct {
154	Name          string
155	Driver        string
156	User          string
157	Config        map[string]interface{}
158	Env           map[string]string
159	Resources     *Resources
160	Meta          map[string]string
161	KillTimeout   *time.Duration `mapstructure:"kill_timeout"`
162	LogConfig     *LogConfig     `mapstructure:"logs"`
163	ShutdownDelay *time.Duration `mapstructure:"shutdown_delay"`
164	KillSignal    string         `mapstructure:"kill_signal"`
165}
166
167// ConsulProxy represents a Consul Connect sidecar proxy jobspec stanza.
168type ConsulProxy struct {
169	LocalServiceAddress string `mapstructure:"local_service_address"`
170	LocalServicePort    int    `mapstructure:"local_service_port"`
171	Upstreams           []*ConsulUpstream
172	Config              map[string]interface{}
173}
174
175// ConsulUpstream represents a Consul Connect upstream jobspec stanza.
176type ConsulUpstream struct {
177	DestinationName string `mapstructure:"destination_name"`
178	LocalBindPort   int    `mapstructure:"local_bind_port"`
179}
180