1package structs
2
3import (
4	"time"
5
6	"github.com/hashicorp/consul/api"
7	"github.com/hashicorp/consul/lib"
8	"github.com/hashicorp/consul/types"
9)
10
11// CheckDefinition is used to JSON decode the Check definitions
12type CheckDefinition struct {
13	ID        types.CheckID
14	Name      string
15	Notes     string
16	ServiceID string
17	Token     string
18	Status    string
19
20	// Copied fields from CheckType without the fields
21	// already present in CheckDefinition:
22	//
23	//   ID (CheckID), Name, Status, Notes
24	//
25	ScriptArgs                     []string
26	HTTP                           string
27	H2PING                         string
28	Header                         map[string][]string
29	Method                         string
30	Body                           string
31	TCP                            string
32	Interval                       time.Duration
33	DockerContainerID              string
34	Shell                          string
35	GRPC                           string
36	GRPCUseTLS                     bool
37	TLSServerName                  string
38	TLSSkipVerify                  bool
39	AliasNode                      string
40	AliasService                   string
41	Timeout                        time.Duration
42	TTL                            time.Duration
43	SuccessBeforePassing           int
44	FailuresBeforeCritical         int
45	DeregisterCriticalServiceAfter time.Duration
46	OutputMaxSize                  int
47
48	EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
49}
50
51func (t *CheckDefinition) UnmarshalJSON(data []byte) (err error) {
52	type Alias CheckDefinition
53	aux := &struct {
54		// Parse special values
55		Interval                       interface{}
56		Timeout                        interface{}
57		TTL                            interface{}
58		DeregisterCriticalServiceAfter interface{}
59
60		// Translate fields
61
62		// "args" -> ScriptArgs
63		Args                                []string    `json:"args"`
64		ScriptArgsSnake                     []string    `json:"script_args"`
65		DeregisterCriticalServiceAfterSnake interface{} `json:"deregister_critical_service_after"`
66		DockerContainerIDSnake              string      `json:"docker_container_id"`
67		TLSServerNameSnake                  string      `json:"tls_server_name"`
68		TLSSkipVerifySnake                  bool        `json:"tls_skip_verify"`
69		GRPCUseTLSSnake                     bool        `json:"grpc_use_tls"`
70		ServiceIDSnake                      string      `json:"service_id"`
71
72		*Alias
73	}{
74		Alias: (*Alias)(t),
75	}
76	if err = lib.UnmarshalJSON(data, &aux); err != nil {
77		return err
78	}
79
80	// Translate Fields
81	if aux.DeregisterCriticalServiceAfter == nil {
82		aux.DeregisterCriticalServiceAfter = aux.DeregisterCriticalServiceAfterSnake
83	}
84	if len(t.ScriptArgs) == 0 {
85		t.ScriptArgs = aux.Args
86	}
87	if len(t.ScriptArgs) == 0 {
88		t.ScriptArgs = aux.ScriptArgsSnake
89	}
90	if t.DockerContainerID == "" {
91		t.DockerContainerID = aux.DockerContainerIDSnake
92	}
93	if t.TLSServerName == "" {
94		t.TLSServerName = aux.TLSServerNameSnake
95	}
96	if aux.TLSSkipVerifySnake {
97		t.TLSSkipVerify = aux.TLSSkipVerifySnake
98	}
99	if aux.GRPCUseTLSSnake {
100		t.GRPCUseTLS = aux.GRPCUseTLSSnake
101	}
102	if t.ServiceID == "" {
103		t.ServiceID = aux.ServiceIDSnake
104	}
105
106	// Parse special values
107	if aux.Interval != nil {
108		switch v := aux.Interval.(type) {
109		case string:
110			if t.Interval, err = time.ParseDuration(v); err != nil {
111				return err
112			}
113		case float64:
114			t.Interval = time.Duration(v)
115		}
116	}
117	if aux.Timeout != nil {
118		switch v := aux.Timeout.(type) {
119		case string:
120			if t.Timeout, err = time.ParseDuration(v); err != nil {
121				return err
122			}
123		case float64:
124			t.Timeout = time.Duration(v)
125		}
126	}
127	if aux.TTL != nil {
128		switch v := aux.TTL.(type) {
129		case string:
130			if t.TTL, err = time.ParseDuration(v); err != nil {
131				return err
132			}
133		case float64:
134			t.TTL = time.Duration(v)
135		}
136	}
137	if aux.DeregisterCriticalServiceAfter != nil {
138		switch v := aux.DeregisterCriticalServiceAfter.(type) {
139		case string:
140			if t.DeregisterCriticalServiceAfter, err = time.ParseDuration(v); err != nil {
141				return err
142			}
143		case float64:
144			t.DeregisterCriticalServiceAfter = time.Duration(v)
145		}
146	}
147
148	return nil
149}
150
151func (c *CheckDefinition) HealthCheck(node string) *HealthCheck {
152	health := &HealthCheck{
153		Node:           node,
154		CheckID:        c.ID,
155		Name:           c.Name,
156		Status:         api.HealthCritical,
157		Notes:          c.Notes,
158		ServiceID:      c.ServiceID,
159		Interval:       c.Interval.String(),
160		Timeout:        c.Timeout.String(),
161		EnterpriseMeta: c.EnterpriseMeta,
162	}
163	if c.Status != "" {
164		health.Status = c.Status
165	}
166	if health.CheckID == "" && health.Name != "" {
167		health.CheckID = types.CheckID(health.Name)
168	}
169	return health
170}
171
172func (c *CheckDefinition) CheckType() *CheckType {
173	return &CheckType{
174		CheckID: c.ID,
175		Name:    c.Name,
176		Status:  c.Status,
177		Notes:   c.Notes,
178
179		ScriptArgs:                     c.ScriptArgs,
180		AliasNode:                      c.AliasNode,
181		AliasService:                   c.AliasService,
182		HTTP:                           c.HTTP,
183		H2PING:                         c.H2PING,
184		GRPC:                           c.GRPC,
185		GRPCUseTLS:                     c.GRPCUseTLS,
186		Header:                         c.Header,
187		Method:                         c.Method,
188		Body:                           c.Body,
189		OutputMaxSize:                  c.OutputMaxSize,
190		TCP:                            c.TCP,
191		Interval:                       c.Interval,
192		DockerContainerID:              c.DockerContainerID,
193		Shell:                          c.Shell,
194		TLSServerName:                  c.TLSServerName,
195		TLSSkipVerify:                  c.TLSSkipVerify,
196		Timeout:                        c.Timeout,
197		TTL:                            c.TTL,
198		SuccessBeforePassing:           c.SuccessBeforePassing,
199		FailuresBeforeCritical:         c.FailuresBeforeCritical,
200		DeregisterCriticalServiceAfter: c.DeregisterCriticalServiceAfter,
201	}
202}
203