Skip to content

Commit 3396c38

Browse files
tremesJoaoFula
authored andcommitted
OCPBUGS-16017: update DataGather CR status in case of job failure (openshift#809)
1 parent 84b1d2b commit 3396c38

File tree

5 files changed

+184
-73
lines changed

5 files changed

+184
-73
lines changed

pkg/controller/gather_commands.go

+5-28
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (d *GatherJob) GatherAndUpload(kubeConfig, protoKubeConfig *rest.Config) er
141141
return err
142142
}
143143

144-
dataGatherCR, err = updateDataGatherStatus(ctx, *insightClient, dataGatherCR.DeepCopy(), insightsv1alpha1.Pending, nil)
144+
dataGatherCR, err = status.UpdateDataGatherStatus(ctx, insightClient, dataGatherCR.DeepCopy(), insightsv1alpha1.Pending, nil)
145145
if err != nil {
146146
klog.Error("failed to update coresponding DataGather custom resource: %v", err)
147147
return err
@@ -180,7 +180,7 @@ func (d *GatherJob) GatherAndUpload(kubeConfig, protoKubeConfig *rest.Config) er
180180
)
181181
uploader := insightsuploader.New(nil, insightsClient, configObserver, nil, nil, 0)
182182

183-
dataGatherCR, err = updateDataGatherStatus(ctx, *insightClient, dataGatherCR, insightsv1alpha1.Running, nil)
183+
dataGatherCR, err = status.UpdateDataGatherStatus(ctx, insightClient, dataGatherCR, insightsv1alpha1.Running, nil)
184184
if err != nil {
185185
klog.Error("failed to update coresponding DataGather custom resource: %v", err)
186186
return err
@@ -214,7 +214,7 @@ func (d *GatherJob) GatherAndUpload(kubeConfig, protoKubeConfig *rest.Config) er
214214
if err != nil {
215215
conditions = append(conditions, status.DataRecordedCondition(metav1.ConditionFalse, "RecordingFailed",
216216
fmt.Sprintf("Failed to record data: %v", err)))
217-
_, recErr := updateDataGatherStatus(ctx, *insightClient, dataGatherCR, insightsv1alpha1.Failed, conditions)
217+
_, recErr := status.UpdateDataGatherStatus(ctx, insightClient, dataGatherCR, insightsv1alpha1.Failed, conditions)
218218
if recErr != nil {
219219
klog.Error("data recording failed and the update of DataGaher resource status failed as well: %v", recErr)
220220
}
@@ -229,7 +229,7 @@ func (d *GatherJob) GatherAndUpload(kubeConfig, protoKubeConfig *rest.Config) er
229229
klog.Error(err)
230230
conditions = append(conditions, status.DataUploadedCondition(metav1.ConditionFalse, reason,
231231
fmt.Sprintf("Failed to upload data: %v", err)))
232-
_, updateErr := updateDataGatherStatus(ctx, *insightClient, dataGatherCR, insightsv1alpha1.Failed, conditions)
232+
_, updateErr := status.UpdateDataGatherStatus(ctx, insightClient, dataGatherCR, insightsv1alpha1.Failed, conditions)
233233
if updateErr != nil {
234234
klog.Error("data upload failed and the update of DataGaher resource status failed as well: %v", updateErr)
235235
}
@@ -240,7 +240,7 @@ func (d *GatherJob) GatherAndUpload(kubeConfig, protoKubeConfig *rest.Config) er
240240
dataGatherCR.Status.InsightsRequestID = insightsRequestID
241241
conditions = append(conditions, status.DataUploadedCondition(metav1.ConditionTrue, reason, ""))
242242

243-
_, err = updateDataGatherStatus(ctx, *insightClient, dataGatherCR, insightsv1alpha1.Completed, conditions)
243+
_, err = status.UpdateDataGatherStatus(ctx, insightClient, dataGatherCR, insightsv1alpha1.Completed, conditions)
244244
if err != nil {
245245
klog.Error(err)
246246
return err
@@ -271,26 +271,3 @@ func record(functionReports []gather.GathererFunctionReport,
271271
}
272272
return recdriver.LastArchive()
273273
}
274-
275-
// updateDataGatherStatus updates status' time attributes, state and conditions
276-
// of the provided DataGather resource
277-
func updateDataGatherStatus(ctx context.Context,
278-
insightsClient insightsv1alpha1cli.InsightsV1alpha1Client,
279-
dataGatherCR *insightsv1alpha1.DataGather,
280-
newState insightsv1alpha1.DataGatherState, conditions []metav1.Condition) (*insightsv1alpha1.DataGather, error) {
281-
switch newState {
282-
case insightsv1alpha1.Completed:
283-
dataGatherCR.Status.FinishTime = metav1.Now()
284-
case insightsv1alpha1.Failed:
285-
dataGatherCR.Status.FinishTime = metav1.Now()
286-
case insightsv1alpha1.Running:
287-
dataGatherCR.Status.StartTime = metav1.Now()
288-
case insightsv1alpha1.Pending:
289-
// no op
290-
}
291-
dataGatherCR.Status.State = newState
292-
if conditions != nil {
293-
dataGatherCR.Status.Conditions = append(dataGatherCR.Status.Conditions, conditions...)
294-
}
295-
return insightsClient.DataGathers().UpdateStatus(ctx, dataGatherCR, metav1.UpdateOptions{})
296-
}

pkg/controller/periodic/periodic.go

+10-15
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,14 @@ func (c *Controller) GatherJob() {
304304
updateMetrics(dataGatherFinished)
305305
if !dataGatheredOK {
306306
klog.Errorf("Last data gathering %v was not successful", dataGatherFinished.Name)
307+
conditions := []metav1.Condition{
308+
status.DataRecordedCondition(metav1.ConditionFalse, "JobNotSucceeded", ""),
309+
status.DataUploadedCondition(metav1.ConditionFalse, "JobNotSucceeded", ""),
310+
}
311+
_, err = status.UpdateDataGatherStatus(ctx, c.dataGatherClient, dataGatherFinished, insightsv1alpha1.Failed, conditions)
312+
if err != nil {
313+
klog.Error("Failed to update failed DataGather resource %s: %v ", dataGatherFinished.Name, err)
314+
}
307315
return
308316
}
309317

@@ -511,7 +519,7 @@ func (c *Controller) createDataGatherAttributeValues() ([]string, insightsv1alph
511519
// wasDataGatherSuccessful reads status conditions of the provided "dataGather" "datagather.insights.openshift.io"
512520
// custom resource and checks whether the data was successfully uploaded or not and updates status accordingly
513521
func (c *Controller) wasDataGatherSuccessful(dataGather *insightsv1alpha1.DataGather) bool {
514-
dataUploadedCon := getConditionByStatus(dataGather, status.DataUploaded)
522+
dataUploadedCon := status.GetConditionByStatus(dataGather, status.DataUploaded)
515523
statusSummary := controllerstatus.Summary{
516524
Operation: controllerstatus.Uploading,
517525
Healthy: true,
@@ -533,24 +541,11 @@ func (c *Controller) wasDataGatherSuccessful(dataGather *insightsv1alpha1.DataGa
533541
return statusSummary.Healthy
534542
}
535543

536-
// getConditionByStatus tries to get the condition with the provided condition status
537-
// from the provided "datagather" resource. Returns nil when no condition is found.
538-
func getConditionByStatus(dataGather *insightsv1alpha1.DataGather, conStatus string) *metav1.Condition {
539-
var dataUploadedCon *metav1.Condition
540-
for i := range dataGather.Status.Conditions {
541-
con := dataGather.Status.Conditions[i]
542-
if con.Type == conStatus {
543-
dataUploadedCon = &con
544-
}
545-
}
546-
return dataUploadedCon
547-
}
548-
549544
// updateMetrics reads the HTTP status code from the reason of the "DataUploaded" condition
550545
// from the provided "datagather" resource and increments
551546
// the "insightsclient_request_send_total" Prometheus metric accordingly.
552547
func updateMetrics(dataGather *insightsv1alpha1.DataGather) {
553-
dataUploadedCon := getConditionByStatus(dataGather, status.DataUploaded)
548+
dataUploadedCon := status.GetConditionByStatus(dataGather, status.DataUploaded)
554549
var statusCode int
555550
if dataUploadedCon == nil {
556551
statusCode = 0

pkg/controller/status/datagather_conditions.go

-30
This file was deleted.
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package status
2+
3+
import (
4+
"context"
5+
6+
insightsv1alpha1 "github.com/openshift/api/insights/v1alpha1"
7+
insightsv1alpha1cli "github.com/openshift/client-go/insights/clientset/versioned/typed/insights/v1alpha1"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
)
10+
11+
const (
12+
DataUploaded = "DataUploaded"
13+
DataRecorded = "DataRecorded"
14+
)
15+
16+
// DataUploadedCondition returns new "DataUploaded" status condition with provided status, reason and message
17+
func DataUploadedCondition(status metav1.ConditionStatus, reason, message string) metav1.Condition {
18+
return metav1.Condition{
19+
Type: DataUploaded,
20+
LastTransitionTime: metav1.Now(),
21+
Status: status,
22+
Reason: reason,
23+
Message: message,
24+
}
25+
}
26+
27+
// DataRecordedCondition returns new "DataRecorded" status condition with provided status, reason and message
28+
func DataRecordedCondition(status metav1.ConditionStatus, reason, message string) metav1.Condition {
29+
return metav1.Condition{
30+
Type: DataRecorded,
31+
LastTransitionTime: metav1.Now(),
32+
Status: status,
33+
Reason: reason,
34+
Message: message,
35+
}
36+
}
37+
38+
// updateDataGatherStatus updates status' time attributes, state and conditions
39+
// of the provided DataGather resource
40+
func UpdateDataGatherStatus(ctx context.Context,
41+
insightsClient insightsv1alpha1cli.InsightsV1alpha1Interface,
42+
dataGatherCR *insightsv1alpha1.DataGather,
43+
newState insightsv1alpha1.DataGatherState, conditions []metav1.Condition) (*insightsv1alpha1.DataGather, error) {
44+
switch newState {
45+
case insightsv1alpha1.Completed:
46+
dataGatherCR.Status.FinishTime = metav1.Now()
47+
case insightsv1alpha1.Failed:
48+
dataGatherCR.Status.FinishTime = metav1.Now()
49+
case insightsv1alpha1.Running:
50+
dataGatherCR.Status.StartTime = metav1.Now()
51+
case insightsv1alpha1.Pending:
52+
// no op
53+
}
54+
dataGatherCR.Status.State = newState
55+
if conditions != nil {
56+
dataGatherCR.Status.Conditions = append(dataGatherCR.Status.Conditions, conditions...)
57+
}
58+
return insightsClient.DataGathers().UpdateStatus(ctx, dataGatherCR, metav1.UpdateOptions{})
59+
}
60+
61+
// GetConditionByStatus tries to get the condition with the provided condition status
62+
// from the provided "datagather" resource. Returns nil when no condition is found.
63+
func GetConditionByStatus(dataGather *insightsv1alpha1.DataGather, conStatus string) *metav1.Condition {
64+
var dataUploadedCon *metav1.Condition
65+
for i := range dataGather.Status.Conditions {
66+
con := dataGather.Status.Conditions[i]
67+
if con.Type == conStatus {
68+
dataUploadedCon = &con
69+
}
70+
}
71+
return dataUploadedCon
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package status
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/openshift/api/insights/v1alpha1"
8+
insightsFakeCli "github.com/openshift/client-go/insights/clientset/versioned/fake"
9+
"github.com/stretchr/testify/assert"
10+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
)
12+
13+
func TestUpdateDataGatherStatus(t *testing.T) {
14+
tests := []struct {
15+
name string
16+
dataGather *v1alpha1.DataGather
17+
dgState v1alpha1.DataGatherState
18+
updatingConditions []metav1.Condition
19+
expectedDataRecordedCon metav1.Condition
20+
expectedDataUploadedCon metav1.Condition
21+
}{
22+
{
23+
name: "updating DataGather to completed state",
24+
dataGather: &v1alpha1.DataGather{
25+
ObjectMeta: metav1.ObjectMeta{
26+
Name: "test-datagather-1",
27+
},
28+
},
29+
dgState: v1alpha1.Completed,
30+
updatingConditions: []metav1.Condition{
31+
DataRecordedCondition(metav1.ConditionTrue, "AsExpected", ""),
32+
DataUploadedCondition(metav1.ConditionTrue, "HttpStatus200", "testing message"),
33+
},
34+
expectedDataRecordedCon: metav1.Condition{
35+
Type: DataRecorded,
36+
Status: metav1.ConditionTrue,
37+
Reason: "AsExpected",
38+
},
39+
expectedDataUploadedCon: metav1.Condition{
40+
Type: DataUploaded,
41+
Status: metav1.ConditionTrue,
42+
Reason: "HttpStatus200",
43+
Message: "testing message",
44+
},
45+
},
46+
{
47+
name: "updating DataGather to failed state",
48+
dataGather: &v1alpha1.DataGather{
49+
ObjectMeta: metav1.ObjectMeta{
50+
Name: "test-datagather-1",
51+
},
52+
},
53+
dgState: v1alpha1.Failed,
54+
updatingConditions: []metav1.Condition{
55+
DataRecordedCondition(metav1.ConditionFalse, "Failure", "testing error message"),
56+
DataUploadedCondition(metav1.ConditionFalse, "HttpStatus403", "testing message"),
57+
},
58+
expectedDataRecordedCon: metav1.Condition{
59+
Type: DataRecorded,
60+
Status: metav1.ConditionFalse,
61+
Reason: "Failure",
62+
Message: "testing error message",
63+
},
64+
expectedDataUploadedCon: metav1.Condition{
65+
Type: DataUploaded,
66+
Status: metav1.ConditionFalse,
67+
Reason: "HttpStatus403",
68+
Message: "testing message",
69+
},
70+
},
71+
}
72+
73+
for _, tt := range tests {
74+
t.Run(tt.name, func(t *testing.T) {
75+
cs := insightsFakeCli.NewSimpleClientset()
76+
createdDG, err := cs.InsightsV1alpha1().DataGathers().Create(context.Background(), tt.dataGather, metav1.CreateOptions{})
77+
assert.NoError(t, err)
78+
updatedDG, err := UpdateDataGatherStatus(context.Background(), cs.InsightsV1alpha1(),
79+
createdDG, tt.dgState, tt.updatingConditions)
80+
assert.NoError(t, err)
81+
assert.NotNil(t, updatedDG.Status.StartTime)
82+
assert.NotNil(t, updatedDG.Status.FinishTime)
83+
84+
dataRecordedCon := GetConditionByStatus(updatedDG, DataRecorded)
85+
assert.NotNil(t, dataRecordedCon)
86+
assert.Equal(t, tt.expectedDataRecordedCon.Reason, dataRecordedCon.Reason)
87+
assert.Equal(t, tt.expectedDataRecordedCon.Status, dataRecordedCon.Status)
88+
assert.Equal(t, tt.expectedDataRecordedCon.Message, dataRecordedCon.Message)
89+
90+
dataUploadedCon := GetConditionByStatus(updatedDG, DataUploaded)
91+
assert.NotNil(t, dataRecordedCon)
92+
assert.Equal(t, tt.expectedDataUploadedCon.Reason, dataUploadedCon.Reason)
93+
assert.Equal(t, tt.expectedDataUploadedCon.Status, dataUploadedCon.Status)
94+
assert.Equal(t, tt.expectedDataUploadedCon.Message, dataUploadedCon.Message)
95+
})
96+
}
97+
}

0 commit comments

Comments
 (0)