@@ -3,13 +3,18 @@ package ocm
3
3
import (
4
4
"context"
5
5
"encoding/json"
6
+ "fmt"
7
+ "net/http"
6
8
"time"
7
9
8
10
"github.com/openshift/insights-operator/pkg/config"
11
+ "github.com/openshift/insights-operator/pkg/controller/status"
12
+ "github.com/openshift/insights-operator/pkg/controllerstatus"
9
13
"github.com/openshift/insights-operator/pkg/insights/insightsclient"
10
14
v1 "k8s.io/api/core/v1"
11
15
"k8s.io/apimachinery/pkg/api/errors"
12
16
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
+ "k8s.io/apimachinery/pkg/util/wait"
13
18
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
14
19
"k8s.io/klog/v2"
15
20
)
@@ -21,6 +26,7 @@ const (
21
26
22
27
// Controller holds all the required resources to be able to communicate with OCM API
23
28
type Controller struct {
29
+ controllerstatus.Simple
24
30
coreClient corev1client.CoreV1Interface
25
31
ctx context.Context
26
32
configurator Configurator
@@ -45,6 +51,7 @@ type ScaResponse struct {
45
51
func New (ctx context.Context , coreClient corev1client.CoreV1Interface , configurator Configurator ,
46
52
insightsClient * insightsclient.Client ) * Controller {
47
53
return & Controller {
54
+ Simple : controllerstatus.Simple {Name : "ocmcontroller" },
48
55
coreClient : coreClient ,
49
56
ctx : ctx ,
50
57
configurator : configurator ,
@@ -79,9 +86,25 @@ func (c *Controller) Run() {
79
86
}
80
87
81
88
func (c * Controller ) requestDataAndCheckSecret (endpoint string ) {
82
- data , err := c .client . RecvSCACerts ( c . ctx , endpoint )
89
+ data , err := c .requestSCAWithExpBackoff ( endpoint )
83
90
if err != nil {
84
- klog .Errorf ("Failed to retrieve data: %v" , err )
91
+ // in case of any error other than 404 mark the operator as degraded
92
+ c .Simple .UpdateStatus (controllerstatus.Summary {
93
+ Operation : controllerstatus .PullingSCACerts ,
94
+ Reason : "FailedToPullSCACerts" ,
95
+ Message : fmt .Sprintf ("Failed to pull SCA certs from %s: %v" , endpoint , err ),
96
+ })
97
+ return
98
+ }
99
+ // handle the case with HTTP 404
100
+ if len (data ) == 0 {
101
+ msg := fmt .Sprintf ("Received no SCA certs from the %s. Please check if it's enabled for your organization." , endpoint )
102
+ klog .Info (msg )
103
+ c .Simple .UpdateStatus (controllerstatus.Summary {
104
+ Operation : controllerstatus .PullingSCACerts ,
105
+ Message : msg ,
106
+ Healthy : true ,
107
+ })
85
108
return
86
109
}
87
110
var ocmRes ScaResponse
@@ -98,6 +121,11 @@ func (c *Controller) requestDataAndCheckSecret(endpoint string) {
98
121
return
99
122
}
100
123
klog .Infof ("%s secret successfully updated" , secretName )
124
+ c .Simple .UpdateStatus (controllerstatus.Summary {
125
+ Operation : controllerstatus .PullingSCACerts ,
126
+ Message : fmt .Sprintf ("SCA certs successfully updated in the %s secret" , secretName ),
127
+ Healthy : true ,
128
+ })
101
129
}
102
130
103
131
// checkSecret checks "etc-pki-entitlement" secret in the "openshift-config-managed" namespace.
@@ -156,3 +184,41 @@ func (c *Controller) updateSecret(s *v1.Secret, ocmData *ScaResponse) (*v1.Secre
156
184
}
157
185
return s , nil
158
186
}
187
+
188
+ // requestSCAWithExpBackoff queries OCM API with exponential backoff and returns
189
+ // an error only in case of an HTTP error other than 404 received from the OCM API.
190
+ // Data return value still can be an empty array in case of HTTP 404 error.
191
+ func (c * Controller ) requestSCAWithExpBackoff (endpoint string ) ([]byte , error ) {
192
+ bo := wait.Backoff {
193
+ Duration : c .configurator .Config ().OCMConfig .Interval / 32 , // 15 min by default
194
+ Factor : 2 ,
195
+ Jitter : 0 ,
196
+ Steps : status .OCMAPIFailureCountThreshold ,
197
+ Cap : c .configurator .Config ().OCMConfig .Interval ,
198
+ }
199
+ var data []byte
200
+ err := wait .ExponentialBackoff (bo , func () (bool , error ) {
201
+ var err error
202
+ data , err = c .client .RecvSCACerts (c .ctx , endpoint )
203
+ if err != nil {
204
+ // don't try again in case it's not an HTTP error - it could mean we're in disconnected env
205
+ if ! insightsclient .IsHttpError (err ) {
206
+ klog .Errorf ("Failed to request the SCA certs: %v" , err )
207
+ return true , nil
208
+ }
209
+ httpErr := err .(insightsclient.HttpError )
210
+ // don't try again in case of 404
211
+ if httpErr .StatusCode == http .StatusNotFound {
212
+ return true , nil
213
+ }
214
+ klog .Errorf ("%v. Trying again in %s" , httpErr , bo .Step ())
215
+ return false , nil
216
+ }
217
+ return true , nil
218
+ })
219
+ // exp. backoff timeouted -> error
220
+ if err != nil {
221
+ return nil , fmt .Errorf ("timed out waiting for the successful response from %s" , endpoint )
222
+ }
223
+ return data , nil
224
+ }
0 commit comments