Skip to content

Commit 4b5be0a

Browse files
committed
feat(prometheus client reconciling): be more strict about clearing the previous connection
To avoid stalling connections that are not expected to be kept. E.g. when an invalid secret is provided.
1 parent 29e5a51 commit 4b5be0a

File tree

2 files changed

+87
-24
lines changed

2 files changed

+87
-24
lines changed

pkg/descheduler/descheduler.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ func (d *inClusterPromClientController) reconcileInClusterSAToken() error {
289289
klog.V(2).Infof("Creating Prometheus client (with SA token)")
290290
prometheusClient, transport, err := d.createPrometheusClient(d.prometheusConfig.URL, cfg.BearerToken)
291291
if err != nil {
292+
d.clearConnection()
292293
return fmt.Errorf("unable to create a prometheus client: %v", err)
293294
}
294295
d.promClient = prometheusClient
@@ -306,6 +307,23 @@ func (d *inClusterPromClientController) reconcileInClusterSAToken() error {
306307
return fmt.Errorf("unexpected error when reading in cluster config: %v", err)
307308
}
308309

310+
func clearPromClientConnection(currentPrometheusAuthToken *string, previousPrometheusClientTransport **http.Transport, promClient *promapi.Client) {
311+
*currentPrometheusAuthToken = ""
312+
if *previousPrometheusClientTransport != nil {
313+
(*previousPrometheusClientTransport).CloseIdleConnections()
314+
}
315+
*previousPrometheusClientTransport = nil
316+
*promClient = nil
317+
}
318+
319+
func (d *inClusterPromClientController) clearConnection() {
320+
clearPromClientConnection(&d.currentPrometheusAuthToken, &d.previousPrometheusClientTransport, &d.promClient)
321+
}
322+
323+
func (d *secretBasedPromClientController) clearConnection() {
324+
clearPromClientConnection(&d.currentPrometheusAuthToken, &d.previousPrometheusClientTransport, &d.promClient)
325+
}
326+
309327
func (d *secretBasedPromClientController) runAuthenticationSecretReconciler(ctx context.Context) {
310328
defer utilruntime.HandleCrash()
311329
defer d.queue.ShutDown()
@@ -353,17 +371,13 @@ func (d *secretBasedPromClientController) sync() error {
353371
if err != nil {
354372
// clear the token if the secret is not found
355373
if apierrors.IsNotFound(err) {
356-
d.currentPrometheusAuthToken = ""
357-
if d.previousPrometheusClientTransport != nil {
358-
d.previousPrometheusClientTransport.CloseIdleConnections()
359-
}
360-
d.previousPrometheusClientTransport = nil
361-
d.promClient = nil
374+
d.clearConnection()
362375
}
363376
return fmt.Errorf("unable to get %v/%v secret", ns, name)
364377
}
365378
authToken := string(secretObj.Data[prometheusAuthTokenSecretKey])
366379
if authToken == "" {
380+
d.clearConnection()
367381
return fmt.Errorf("prometheus authentication token secret missing %q data or empty", prometheusAuthTokenSecretKey)
368382
}
369383
if d.currentPrometheusAuthToken == authToken {
@@ -373,6 +387,7 @@ func (d *secretBasedPromClientController) sync() error {
373387
klog.V(2).Infof("authentication secret token updated, recreating prometheus client")
374388
prometheusClient, transport, err := d.createPrometheusClient(prometheusConfig.URL, authToken)
375389
if err != nil {
390+
d.clearConnection()
376391
return fmt.Errorf("unable to create a prometheus client: %v", err)
377392
}
378393
d.promClient = prometheusClient

pkg/descheduler/descheduler_test.go

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,14 +2175,15 @@ func TestPromClientControllerSync_ClientCreation(t *testing.T) {
21752175

21762176
func TestPromClientControllerSync_EventHandler(t *testing.T) {
21772177
testCases := []struct {
2178-
name string
2179-
operation func(ctx context.Context, fakeClient *fakeclientset.Clientset) error
2180-
processItem bool
2181-
expectedPromClientSet bool
2182-
expectedCreatedClientsCount int
2183-
expectedCurrentToken string
2184-
expectedPreviousTransportCleared bool
2185-
expectDifferentClients bool
2178+
name string
2179+
operation func(ctx context.Context, fakeClient *fakeclientset.Clientset) error
2180+
processItem bool
2181+
expectedPromClientSet bool
2182+
expectedCreatedClientsCount int
2183+
expectedCurrentToken string
2184+
expectedPreviousTransportCleared bool
2185+
expectDifferentClients bool
2186+
expectCreatePrometheusClientError bool
21862187
}{
21872188
// Check initial conditions
21882189
{
@@ -2219,15 +2220,56 @@ func TestPromClientControllerSync_EventHandler(t *testing.T) {
22192220
expectedCurrentToken: "token-2",
22202221
expectDifferentClients: true,
22212222
},
2223+
{
2224+
name: "update secret with invalid data",
2225+
operation: func(ctx context.Context, fakeClient *fakeclientset.Clientset) error {
2226+
secret := newPrometheusAuthSecret(withToken("token-3"))
2227+
secret.Data[prometheusAuthTokenSecretKey] = []byte{}
2228+
_, err := fakeClient.CoreV1().Secrets(secret.Namespace).Update(ctx, secret, metav1.UpdateOptions{})
2229+
return err
2230+
},
2231+
processItem: true,
2232+
expectedPromClientSet: false,
2233+
expectedCreatedClientsCount: 2,
2234+
expectedCurrentToken: "",
2235+
expectDifferentClients: true,
2236+
},
2237+
{
2238+
name: "update secret with valid data",
2239+
operation: func(ctx context.Context, fakeClient *fakeclientset.Clientset) error {
2240+
secret := newPrometheusAuthSecret(withToken("token-4"))
2241+
_, err := fakeClient.CoreV1().Secrets(secret.Namespace).Update(ctx, secret, metav1.UpdateOptions{})
2242+
return err
2243+
},
2244+
processItem: true,
2245+
expectedPromClientSet: true,
2246+
expectedCreatedClientsCount: 3,
2247+
expectedCurrentToken: "token-4",
2248+
expectDifferentClients: true,
2249+
},
2250+
{
2251+
name: "update secret with valid data but createPrometheusClient failing",
2252+
operation: func(ctx context.Context, fakeClient *fakeclientset.Clientset) error {
2253+
secret := newPrometheusAuthSecret(withToken("token-5"))
2254+
_, err := fakeClient.CoreV1().Secrets(secret.Namespace).Update(ctx, secret, metav1.UpdateOptions{})
2255+
return err
2256+
},
2257+
processItem: true,
2258+
expectedPromClientSet: false,
2259+
expectedCreatedClientsCount: 3,
2260+
expectedCurrentToken: "",
2261+
expectDifferentClients: true,
2262+
expectCreatePrometheusClientError: true,
2263+
},
22222264
{
22232265
name: "delete secret",
22242266
operation: func(ctx context.Context, fakeClient *fakeclientset.Clientset) error {
2225-
secret := newPrometheusAuthSecret(withToken("token-2"))
2267+
secret := newPrometheusAuthSecret(withToken("token-5"))
22262268
return fakeClient.CoreV1().Secrets(secret.Namespace).Delete(ctx, secret.Name, metav1.DeleteOptions{})
22272269
},
22282270
processItem: true,
22292271
expectedPromClientSet: false,
2230-
expectedCreatedClientsCount: 2,
2272+
expectedCreatedClientsCount: 3,
22312273
expectedCurrentToken: "",
22322274
expectedPreviousTransportCleared: true,
22332275
},
@@ -2279,16 +2321,22 @@ func TestPromClientControllerSync_EventHandler(t *testing.T) {
22792321
// Track created clients to verify different instances
22802322
var createdClients []promapi.Client
22812323
var createdClientsMu sync.Mutex
2282-
ctrl.createPrometheusClient = func(url, token string) (promapi.Client, *http.Transport, error) {
2283-
client := &mockPrometheusClient{name: "client-" + token}
2284-
createdClientsMu.Lock()
2285-
createdClients = append(createdClients, client)
2286-
createdClientsMu.Unlock()
2287-
return client, &http.Transport{}, nil
2288-
}
22892324

22902325
for _, tc := range testCases {
22912326
t.Run(tc.name, func(t *testing.T) {
2327+
ctrl.mu.Lock()
2328+
ctrl.createPrometheusClient = func(url, token string) (promapi.Client, *http.Transport, error) {
2329+
if tc.expectCreatePrometheusClientError {
2330+
return nil, &http.Transport{}, fmt.Errorf("error creating a prometheus client")
2331+
}
2332+
client := &mockPrometheusClient{name: "client-" + token}
2333+
createdClientsMu.Lock()
2334+
createdClients = append(createdClients, client)
2335+
createdClientsMu.Unlock()
2336+
return client, &http.Transport{}, nil
2337+
}
2338+
ctrl.mu.Unlock()
2339+
22922340
if err := tc.operation(ctx, fakeClient); err != nil {
22932341
t.Fatalf("Failed to execute operation: %v", err)
22942342
}
@@ -2430,7 +2478,7 @@ func TestReconcileInClusterSAToken(t *testing.T) {
24302478
},
24312479
expectedErr: fmt.Errorf("unable to create a prometheus client: failed to create client"),
24322480
expectClientCreated: false,
2433-
expectCurrentToken: "old-token",
2481+
expectCurrentToken: "",
24342482
expectPreviousTransportCleared: false,
24352483
expectPromClientCleared: false,
24362484
},

0 commit comments

Comments
 (0)