@@ -4,28 +4,45 @@ import (
4
4
"context"
5
5
"fmt"
6
6
"sort"
7
+ "strings"
7
8
"time"
8
9
9
10
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
10
11
"k8s.io/apimachinery/pkg/util/wait"
11
12
"k8s.io/klog/v2"
12
13
14
+ v1 "github.com/openshift/api/operator/v1"
15
+ operatorv1client "github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1"
13
16
"github.com/openshift/insights-operator/pkg/anonymization"
14
17
"github.com/openshift/insights-operator/pkg/config/configobserver"
15
18
"github.com/openshift/insights-operator/pkg/controllerstatus"
16
19
"github.com/openshift/insights-operator/pkg/gather"
17
20
"github.com/openshift/insights-operator/pkg/gatherers"
18
21
"github.com/openshift/insights-operator/pkg/recorder"
22
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23
+ )
24
+
25
+ const (
26
+ DataGatheredCondition = "DataGathered"
27
+ // NoDataGathered is a reason when there is no data gathered - e.g the resource is not in a cluster
28
+ NoDataGatheredReason = "NoData"
29
+ // GatherError is a reason when there is some error and no data gathered
30
+ GatherErrorReason = "Error"
31
+ // GatheredOK is a reason when data is gathered as expected
32
+ GatherOKReason = "GatheredOK"
33
+ // GatherWithError is a reason when data is gathered partially or with another error message
34
+ GatherWithErrorReason = "GatheredWithError"
19
35
)
20
36
21
37
// Controller periodically runs gatherers, records their results to the recorder
22
38
// and flushes the recorder to create archives
23
39
type Controller struct {
24
- configurator configobserver.Configurator
25
- recorder recorder.FlushInterface
26
- gatherers []gatherers.Interface
27
- statuses map [string ]controllerstatus.StatusController
28
- anonymizer * anonymization.Anonymizer
40
+ configurator configobserver.Configurator
41
+ recorder recorder.FlushInterface
42
+ gatherers []gatherers.Interface
43
+ statuses map [string ]controllerstatus.StatusController
44
+ anonymizer * anonymization.Anonymizer
45
+ insightsOperatorCLI operatorv1client.InsightsOperatorInterface
29
46
}
30
47
31
48
// New creates a new instance of Controller which periodically invokes the gatherers
@@ -35,6 +52,7 @@ func New(
35
52
rec recorder.FlushInterface ,
36
53
listGatherers []gatherers.Interface ,
37
54
anonymizer * anonymization.Anonymizer ,
55
+ insightsOperatorCLI operatorv1client.InsightsOperatorInterface ,
38
56
) * Controller {
39
57
statuses := make (map [string ]controllerstatus.StatusController )
40
58
@@ -44,11 +62,12 @@ func New(
44
62
}
45
63
46
64
return & Controller {
47
- configurator : configurator ,
48
- recorder : rec ,
49
- gatherers : listGatherers ,
50
- statuses : statuses ,
51
- anonymizer : anonymizer ,
65
+ configurator : configurator ,
66
+ recorder : rec ,
67
+ gatherers : listGatherers ,
68
+ statuses : statuses ,
69
+ anonymizer : anonymizer ,
70
+ insightsOperatorCLI : insightsOperatorCLI ,
52
71
}
53
72
}
54
73
@@ -114,7 +133,7 @@ func (c *Controller) Gather() {
114
133
}
115
134
116
135
allFunctionReports := make (map [string ]gather.GathererFunctionReport )
117
-
136
+ gatherTime := metav1 . Now ()
118
137
for _ , gatherer := range gatherersToProcess {
119
138
func () {
120
139
name := gatherer .GetName ()
@@ -142,8 +161,11 @@ func (c *Controller) Gather() {
142
161
})
143
162
}()
144
163
}
145
-
146
- err := gather .RecordArchiveMetadata (mapToArray (allFunctionReports ), c .recorder , c .anonymizer )
164
+ err := c .updateOperatorStatusCR (allFunctionReports , gatherTime )
165
+ if err != nil {
166
+ klog .Errorf ("failed to update the Insights Operator CR status: %v" , err )
167
+ }
168
+ err = gather .RecordArchiveMetadata (mapToArray (allFunctionReports ), c .recorder , c .anonymizer )
147
169
if err != nil {
148
170
klog .Errorf ("unable to record archive metadata because of error: %v" , err )
149
171
}
@@ -176,6 +198,76 @@ func (c *Controller) periodicTrigger(stopCh <-chan struct{}) {
176
198
}
177
199
}
178
200
201
+ func (c * Controller ) updateOperatorStatusCR (allFunctionReports map [string ]gather.GathererFunctionReport , gatherTime metav1.Time ) error {
202
+ insightsOperatorCR , err := c .insightsOperatorCLI .Get (context .Background (), "cluster" , metav1.GetOptions {})
203
+ if err != nil {
204
+ return err
205
+ }
206
+
207
+ ioCopy := insightsOperatorCR .DeepCopy ()
208
+ ioCopy .Status .GatherStatus .Gatherers = []v1.GathererStatus {}
209
+ ioCopy .Status .GatherStatus .LastGatherTime = gatherTime
210
+ ioCopy .Status .GatherStatus .LastGatherDuration = metav1.Duration {
211
+ Duration : time .Since (gatherTime .Time ),
212
+ }
213
+
214
+ for k := range allFunctionReports {
215
+ fr := allFunctionReports [k ]
216
+ // duration = 0 means the gatherer didn't run
217
+ if fr .Duration == 0 {
218
+ continue
219
+ }
220
+
221
+ gs := createGathererStatus (& fr )
222
+ ioCopy .Status .GatherStatus .Gatherers = append (ioCopy .Status .GatherStatus .Gatherers , gs )
223
+ }
224
+
225
+ _ , err = c .insightsOperatorCLI .UpdateStatus (context .Background (), ioCopy , metav1.UpdateOptions {})
226
+ if err != nil {
227
+ return err
228
+ }
229
+ return nil
230
+ }
231
+
232
+ func createGathererStatus (gfr * gather.GathererFunctionReport ) v1.GathererStatus {
233
+ gs := v1.GathererStatus {
234
+ Name : gfr .FuncName ,
235
+ LastGatherDuration : metav1.Duration {
236
+ // v.Duration is in milliseconds and we need nanoseconds
237
+ Duration : time .Duration (gfr .Duration * 1000000 ),
238
+ },
239
+ }
240
+ con := metav1.Condition {
241
+ Type : DataGatheredCondition ,
242
+ LastTransitionTime : metav1 .Now (),
243
+ }
244
+
245
+ if gfr .RecordsCount > 0 {
246
+ con .Status = metav1 .ConditionTrue
247
+ con .Reason = GatherOKReason
248
+ con .Message = fmt .Sprintf ("Created %d records in the archive." , gfr .RecordsCount )
249
+
250
+ if len (gfr .Errors ) > 0 {
251
+ con .Reason = GatherWithErrorReason
252
+ con .Message = fmt .Sprintf ("%s Error is: %s" , con .Message , strings .Join (gfr .Errors , "," ))
253
+ }
254
+
255
+ gs .Conditions = append (gs .Conditions , con )
256
+ } else {
257
+ con .Status = metav1 .ConditionFalse
258
+ con .Reason = NoDataGatheredReason
259
+
260
+ if len (gfr .Errors ) > 0 {
261
+ con .Reason = GatherErrorReason
262
+ con .Message = strings .Join (gfr .Errors , "," )
263
+ }
264
+
265
+ gs .Conditions = append (gs .Conditions , con )
266
+ }
267
+
268
+ return gs
269
+ }
270
+
179
271
func mapToArray (m map [string ]gather.GathererFunctionReport ) []gather.GathererFunctionReport {
180
272
a := make ([]gather.GathererFunctionReport , 0 , len (m ))
181
273
for _ , v := range m {
0 commit comments