3
3
*/
4
4
5
5
// SPDX-License-Identifier: MIT
6
- // SPDX-FileCopyrightText: 2022 Steadybit GmbH
6
+ // SPDX-FileCopyrightText: 2024 Steadybit GmbH
7
7
8
8
package extservice
9
9
@@ -32,11 +32,17 @@ var (
32
32
)
33
33
34
34
type ServiceStatusCheckState struct {
35
- ServiceId string
36
- ServiceName string
37
- ClusterName string
38
- End time.Time
39
- ExpectedStatus string
35
+ ServiceId string
36
+ ServiceName string
37
+ ClusterName string
38
+ End time.Time
39
+ ExpectedStatus string
40
+ StatusCheckMode string
41
+ StatusCheckSuccess bool
42
+ }
43
+
44
+ type GetSnapshotApi interface {
45
+ GetServiceSnapshot (ctx context.Context , serviceId string ) (* resty.Response , ViewSnapshotResponseWrapper , error )
40
46
}
41
47
42
48
func NewServiceStatusCheckAction () action_kit_sdk.Action [ServiceStatusCheckState ] {
@@ -105,6 +111,25 @@ func (m *ServiceStatusCheckAction) Describe() action_kit_api.ActionDescription {
105
111
Required : extutil .Ptr (false ),
106
112
Order : extutil .Ptr (2 ),
107
113
},
114
+ {
115
+ Name : "statusCheckMode" ,
116
+ Label : "Status Check Mode" ,
117
+ Description : extutil .Ptr ("How often should the status be expected?" ),
118
+ Type : action_kit_api .String ,
119
+ DefaultValue : extutil .Ptr (statusCheckModeAllTheTime ),
120
+ Options : extutil .Ptr ([]action_kit_api.ParameterOption {
121
+ action_kit_api.ExplicitParameterOption {
122
+ Label : "All the time" ,
123
+ Value : statusCheckModeAllTheTime ,
124
+ },
125
+ action_kit_api.ExplicitParameterOption {
126
+ Label : "At least once" ,
127
+ Value : statusCheckModeAtLeastOnce ,
128
+ },
129
+ }),
130
+ Required : extutil .Ptr (true ),
131
+ Order : extutil .Ptr (4 ),
132
+ },
108
133
},
109
134
Widgets : extutil .Ptr ([]action_kit_api.Widget {
110
135
action_kit_api.StateOverTimeWidget {
@@ -149,12 +174,18 @@ func (m *ServiceStatusCheckAction) Prepare(_ context.Context, state *ServiceStat
149
174
if request .Config ["expectedStatus" ] != nil {
150
175
expectedStatus = fmt .Sprintf ("%v" , request .Config ["expectedStatus" ])
151
176
}
177
+ var statusCheckMode = statusCheckModeAllTheTime
178
+ if request .Config ["statusCheckMode" ] != nil {
179
+ statusCheckMode = fmt .Sprintf ("%v" , request .Config ["statusCheckMode" ])
180
+ }
152
181
153
182
state .ServiceId = serviceId [0 ]
154
183
state .ServiceName = request .Target .Attributes ["k8s.service.name" ][0 ]
155
184
state .ClusterName = request .Target .Attributes ["k8s.cluster-name" ][0 ]
156
185
state .End = end
157
186
state .ExpectedStatus = expectedStatus
187
+ state .StatusCheckMode = statusCheckMode
188
+ state .StatusCheckSuccess = state .StatusCheckMode == statusCheckModeAllTheTime
158
189
159
190
return nil , nil
160
191
}
@@ -164,41 +195,15 @@ func (m *ServiceStatusCheckAction) Start(_ context.Context, _ *ServiceStatusChec
164
195
}
165
196
166
197
func (m * ServiceStatusCheckAction ) Status (ctx context.Context , state * ServiceStatusCheckState ) (* action_kit_api.StatusResult , error ) {
167
- return MonitorStatusCheckStatus (ctx , state , RestyClient )
198
+ return MonitorStatusCheckStatus (ctx , state , Client )
168
199
}
169
200
170
- func MonitorStatusCheckStatus (ctx context.Context , state * ServiceStatusCheckState , client * resty. Client ) (* action_kit_api.StatusResult , error ) {
201
+ func MonitorStatusCheckStatus (ctx context.Context , state * ServiceStatusCheckState , api GetSnapshotApi ) (* action_kit_api.StatusResult , error ) {
171
202
now := time .Now ()
172
-
173
- requestBody := fmt .Sprintf (`{
174
- "_type": "ViewSnapshotRequest",
175
- "query": "(id = \"%s\")",
176
- "queryVersion": "0.0.1",
177
- "metadata": {
178
- "_type": "QueryMetadata",
179
- "groupingEnabled": false,
180
- "showIndirectRelations": false,
181
- "minGroupSize": 0,
182
- "groupedByLayer": false,
183
- "groupedByDomain": false,
184
- "groupedByRelation": false,
185
- "showCause": "NONE",
186
- "autoGrouping": false,
187
- "connectedComponents": false,
188
- "neighboringComponents": false,
189
- "showFullComponent": false
190
- }
191
- }` , state .ServiceId )
192
-
193
- var stackStateResponse ViewSnapshotResponseWrapper
194
- res , err := client .R ().
195
- SetContext (ctx ).
196
- SetBody ([]byte (requestBody )).
197
- SetResult (& stackStateResponse ).
198
- Post ("/snapshot" )
203
+ res , stackStateResponse , err := api .GetServiceSnapshot (ctx , state .ServiceId )
199
204
200
205
if err != nil {
201
- return nil , extutil .Ptr (extension_kit .ToError (fmt .Sprintf ("Failed to retrieve service states from Stack State for Service ID %s. Full response: %v" , state .ServiceId , res .String ()), err ))
206
+ return nil , extutil .Ptr (extension_kit .ToError (fmt .Sprintf ("Failed to retrieve service states from StackState for Service ID %s. Full response: %v" , state .ServiceId , res .String ()), err ))
202
207
}
203
208
204
209
var component Component
@@ -222,15 +227,36 @@ func MonitorStatusCheckStatus(ctx context.Context, state *ServiceStatusCheckStat
222
227
223
228
completed := now .After (state .End )
224
229
var checkError * action_kit_api.ActionKitError
225
- if len (state .ExpectedStatus ) > 0 && component .State .HealthState != state .ExpectedStatus {
226
- checkError = extutil .Ptr (action_kit_api.ActionKitError {
227
- Title : fmt .Sprintf ("Service '%s' (id %s) has status '%s' whereas '%s' is expected." ,
228
- component .Name ,
229
- state .ServiceId ,
230
- component .State .HealthState ,
231
- state .ExpectedStatus ),
232
- Status : extutil .Ptr (action_kit_api .Failed ),
233
- })
230
+ if len (state .ExpectedStatus ) > 0 {
231
+ componentHealthState := component .State .HealthState
232
+ if state .StatusCheckMode == statusCheckModeAllTheTime {
233
+ if componentHealthState != state .ExpectedStatus || ! state .StatusCheckSuccess {
234
+ state .StatusCheckSuccess = false
235
+ completed = true
236
+ checkError = extutil .Ptr (action_kit_api.ActionKitError {
237
+ Title : fmt .Sprintf ("Service '%s' (id %s) has status '%s' whereas '%s' is expected." ,
238
+ component .Name ,
239
+ state .ServiceId ,
240
+ componentHealthState ,
241
+ state .ExpectedStatus ),
242
+ Status : extutil .Ptr (action_kit_api .Failed ),
243
+ })
244
+ }
245
+ } else if state .StatusCheckMode == statusCheckModeAtLeastOnce {
246
+ if componentHealthState == state .ExpectedStatus || state .StatusCheckSuccess {
247
+ state .StatusCheckSuccess = true
248
+ completed = true
249
+ }
250
+ if completed && ! state .StatusCheckSuccess {
251
+ checkError = extutil .Ptr (action_kit_api.ActionKitError {
252
+ Title : fmt .Sprintf ("Service '%s' (id %s) didn't have status '%s' at least once." ,
253
+ component .Name ,
254
+ state .ServiceId ,
255
+ state .ExpectedStatus ),
256
+ Status : extutil .Ptr (action_kit_api .Failed ),
257
+ })
258
+ }
259
+ }
234
260
}
235
261
236
262
metrics := []action_kit_api.Metric {
0 commit comments