1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package v1alpha1
17
18 import (
19 "net/http"
20 "time"
21
22 "github.com/pkg/errors"
23 corev1 "k8s.io/api/core/v1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 )
26
27
28
29
30 type StatusCheck struct {
31 metav1.TypeMeta `json:",inline"`
32 metav1.ObjectMeta `json:"metadata,omitempty"`
33
34
35 Spec StatusCheckSpec `json:"spec"`
36
37
38
39 Status StatusCheckStatus `json:"status,omitempty"`
40 }
41
42 type StatusCheckMode string
43
44 const (
45
46
47 StatusCheckSynchronous StatusCheckMode = "Synchronous"
48
49
50 StatusCheckContinuous StatusCheckMode = "Continuous"
51 )
52
53 type StatusCheckType string
54
55 const (
56 TypeHTTP StatusCheckType = "HTTP"
57 )
58
59 type StatusCheckSpec struct {
60
61
62
63
64 Mode StatusCheckMode `json:"mode,omitempty"`
65
66
67
68
69
70 Type StatusCheckType `json:"type"`
71
72
73
74
75
76
77
78
79
80 Duration *string `json:"duration,omitempty" webhook:"Duration"`
81
82
83
84
85
86
87 TimeoutSeconds int `json:"timeoutSeconds,omitempty"`
88
89
90
91
92
93
94 IntervalSeconds int `json:"intervalSeconds,omitempty"`
95
96
97
98
99
100
101 FailureThreshold int `json:"failureThreshold,omitempty"`
102
103
104
105
106
107
108
109 SuccessThreshold int `json:"successThreshold,omitempty"`
110
111
112
113
114
115
116 RecordsHistoryLimit int `json:"recordsHistoryLimit,omitempty"`
117
118
119 *EmbedStatusCheck `json:",inline,omitempty"`
120 }
121
122 type StatusCheckStatus struct {
123
124
125 StartTime *metav1.Time `json:"startTime,omitempty"`
126
127
128
129 CompletionTime *metav1.Time `json:"completionTime,omitempty"`
130
131
132
133 Count int64 `json:"count,omitempty"`
134
135
136
137
138
139 Conditions []StatusCheckCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
140
141
142
143 Records []StatusCheckRecord `json:"records,omitempty"`
144 }
145
146 type StatusCheckOutcome string
147
148 const (
149 StatusCheckOutcomeSuccess StatusCheckOutcome = "Success"
150 StatusCheckOutcomeFailure StatusCheckOutcome = "Failure"
151 )
152
153 type StatusCheckRecord struct {
154 StartTime *metav1.Time `json:"startTime"`
155 Outcome StatusCheckOutcome `json:"outcome"`
156 }
157
158 type StatusCheckConditionType string
159
160 const (
161
162
163
164
165
166 StatusCheckConditionCompleted StatusCheckConditionType = "Completed"
167
168 StatusCheckConditionDurationExceed StatusCheckConditionType = "DurationExceed"
169
170 StatusCheckConditionFailureThresholdExceed StatusCheckConditionType = "FailureThresholdExceed"
171
172 StatusCheckConditionSuccessThresholdExceed StatusCheckConditionType = "SuccessThresholdExceed"
173 )
174
175 type StatusCheckReason string
176
177 const (
178 StatusCheckDurationExceed StatusCheckReason = "StatusCheckDurationExceed"
179 StatusCheckFailureThresholdExceed StatusCheckReason = "StatusCheckFailureThresholdExceed"
180 StatusCheckSuccessThresholdExceed StatusCheckReason = "StatusCheckSuccessThresholdExceed"
181 StatusCheckExecutionFailed StatusCheckReason = "StatusCheckExecutionFailed"
182 StatusCheckExecutionSucceed StatusCheckReason = "StatusCheckExecutionSucceed"
183 )
184
185 type StatusCheckCondition struct {
186 Type StatusCheckConditionType `json:"type"`
187 Status corev1.ConditionStatus `json:"status"`
188 Reason StatusCheckReason `json:"reason"`
189 LastProbeTime *metav1.Time `json:"lastProbeTime"`
190 LastTransitionTime *metav1.Time `json:"lastTransitionTime"`
191 }
192
193 type EmbedStatusCheck struct {
194
195 HTTPStatusCheck *HTTPStatusCheck `json:"http,omitempty"`
196 }
197
198 type HTTPCriteria struct {
199
200
201
202 StatusCode string `json:"statusCode" webhook:"StatusCode"`
203
204 }
205
206 type HTTPRequestMethod string
207
208 const (
209 MethodGet = "GET"
210 MethodPost = "POST"
211 )
212
213 type HTTPStatusCheck struct {
214 RequestUrl string `json:"url"`
215
216
217
218
219 RequestMethod HTTPRequestMethod `json:"method,omitempty"`
220
221 RequestHeaders http.Header `json:"headers,omitempty"`
222
223 RequestBody string `json:"body,omitempty"`
224
225 Criteria HTTPCriteria `json:"criteria"`
226 }
227
228
229
230 type StatusCheckList struct {
231 metav1.TypeMeta `json:",inline"`
232 metav1.ListMeta `json:"metadata,omitempty"`
233 Items []StatusCheck `json:"items"`
234 }
235
236 func (in *StatusCheckSpec) GetDuration() (*time.Duration, error) {
237 if in.Duration == nil {
238 return nil, nil
239 }
240 duration, err := time.ParseDuration(*in.Duration)
241 if err != nil {
242 return nil, errors.Wrapf(err, "parse duration %s", *in.Duration)
243 }
244 return &duration, nil
245 }
246
247 func (in *StatusCheck) DurationExceed(now time.Time) (bool, time.Duration, error) {
248 if in.Status.StartTime == nil {
249 return false, 0, nil
250 }
251 duration, err := in.Spec.GetDuration()
252 if err != nil {
253 return false, 0, errors.Wrap(err, "get duration")
254 }
255
256 if duration != nil {
257 stopTime := in.Status.StartTime.Add(*duration)
258 if stopTime.Before(now) {
259 return true, 0, nil
260 }
261
262 return false, stopTime.Sub(now), nil
263 }
264
265 return false, 0, nil
266 }
267
268
269 func (in *StatusCheck) IsCompleted() bool {
270 for _, condition := range in.Status.Conditions {
271 if condition.Type == StatusCheckConditionCompleted &&
272 condition.Status == corev1.ConditionTrue {
273 return true
274 }
275 }
276 return false
277 }
278