-
Notifications
You must be signed in to change notification settings - Fork 0
/
healthcheck.go
187 lines (156 loc) · 4.08 KB
/
healthcheck.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package builddef
import (
"fmt"
"reflect"
"strings"
"time"
"github.com/NiR-/zbuild/pkg/image"
"github.com/mitchellh/mapstructure"
)
// HealthcheckConfig represents healthcheck as specified in specialized
// definition files.
type HealthcheckConfig struct {
*HealthcheckHTTP `mapstructure:"http"`
*HealthcheckFCGI `mapstructure:"fcgi"`
*HealthcheckCmd `mapstructure:"cmd"`
Type HealthcheckType
Interval time.Duration
Timeout time.Duration
Retries int
}
func (hc *HealthcheckConfig) IsValid(allowedTypes []string) bool {
if hc == nil {
return true
}
if ok := hc.Type.IsValid(allowedTypes); !ok {
return false
}
switch hc.Type {
case HealthcheckTypeHTTP:
return hc.HealthcheckHTTP != nil
case HealthcheckTypeFCGI:
return hc.HealthcheckFCGI != nil
case HealthcheckTypeCmd:
return hc.HealthcheckCmd != nil
case HealthcheckTypeDisabled:
return true
}
return false
}
func (hc *HealthcheckConfig) IsEnabled() bool {
if hc == nil {
return false
}
return hc.Type != HealthcheckTypeDisabled
}
func (hc *HealthcheckConfig) ToImageConfig() *image.HealthConfig {
if hc == nil {
return nil
}
var test []string
switch hc.Type {
case HealthcheckTypeDisabled:
test = []string{"NONE"}
case HealthcheckTypeCmd:
test = hc.HealthcheckCmd.healthTest()
case HealthcheckTypeHTTP:
test = hc.HealthcheckHTTP.healthTest()
case HealthcheckTypeFCGI:
test = hc.HealthcheckFCGI.healthTest()
}
return &image.HealthConfig{
Test: test,
Interval: hc.Interval,
Timeout: hc.Timeout,
Retries: hc.Retries,
}
}
type HealthcheckType string
func (hcType HealthcheckType) IsValid(allowed []string) bool {
if hcType == HealthcheckTypeDisabled {
return true
}
for _, proto := range allowed {
if proto != string(hcType) {
return true
}
}
return false
}
const (
HealthcheckTypeDisabled = HealthcheckType("disabled")
HealthcheckTypeHTTP = HealthcheckType("http")
HealthcheckTypeFCGI = HealthcheckType("fcgi")
HealthcheckTypeCmd = HealthcheckType("cmd")
)
// HealthcheckHTTP are healthcheck parameters that can be specified in
// specialized definition files when using http healthcheck type.
type HealthcheckHTTP struct {
Path string
Expected string
}
// healthTest returns a string slice containing the command to execute to check
// the health. It's formatted like HealthConfig.Test.
func (hc HealthcheckHTTP) healthTest() []string {
cmd := fmt.Sprintf(
"test \"$(curl --fail http://127.0.0.1/%s)\" = \"%s\"",
strings.TrimLeft(hc.Path, "/"),
hc.Expected)
return []string{"CMD-SHELL", cmd}
}
// HealthcheckFCGI are healthcheck parameters that can be specified in
// specialized definition files when using fcgi healthcheck type.
type HealthcheckFCGI struct {
Path string
Expected string
}
// healthTest returns a string slice containing the command to execute to check
// the health. It's formatted like HealthConfig.Test.
func (hc HealthcheckFCGI) healthTest() []string {
cmd := fmt.Sprintf(
"test \"$(fcgi-client get 127.0.0.1:9000 %s)\" = \"%s\"",
hc.Path,
hc.Expected)
return []string{"CMD-SHELL", cmd}
}
// HealthcheckCmd are healthcheck parameters that can be specified in
// specialized definition files when using cmd healthcheck type.
type HealthcheckCmd struct {
Shell bool
Command []string
}
// healthTest returns a string slice containing the command to execute to check
// the health. It's formatted like HealthConfig.Test.
func (hc HealthcheckCmd) healthTest() []string {
test := make([]string, 1, len(hc.Command)+1)
test[0] = "CMD"
if hc.Shell {
test[0] = "CMD-SHELL"
}
test = append(test, hc.Command...)
return test
}
func DecodeBoolToHealthcheck(
defaultHealthcheck HealthcheckConfig,
) mapstructure.DecodeHookFuncKind {
return func(
from reflect.Kind,
to reflect.Kind,
data interface{},
) (interface{}, error) {
if from != reflect.Bool {
return data, nil
}
if to != reflect.TypeOf(HealthcheckConfig{}).Kind() {
return data, nil
}
val := data.(bool)
if val {
return defaultHealthcheck, nil
}
healthcheck := HealthcheckConfig{
Type: HealthcheckTypeDisabled,
}
return healthcheck, nil
}
}