@@ -2,6 +2,7 @@ package static
2
2
3
3
import (
4
4
"context"
5
+ "errors"
5
6
"fmt"
6
7
"sync"
7
8
"time"
@@ -182,11 +183,11 @@ func (h *eventHandlerImpl) HandleEventBatch(ctx context.Context, logger logr.Log
182
183
183
184
h .setLatestConfiguration (& cfg )
184
185
185
- err = h . updateUpstreamServers (
186
- ctx ,
187
- logger ,
188
- cfg ,
189
- )
186
+ if h . cfg . plus {
187
+ err = h . updateUpstreamServers ( cfg )
188
+ } else {
189
+ err = h . updateNginxConf ( ctx , cfg )
190
+ }
190
191
case state .ClusterStateChange :
191
192
h .version ++
192
193
cfg := dataplane .BuildConfiguration (ctx , gr , h .cfg .serviceResolver , h .version )
@@ -198,10 +199,7 @@ func (h *eventHandlerImpl) HandleEventBatch(ctx context.Context, logger logr.Log
198
199
199
200
h .setLatestConfiguration (& cfg )
200
201
201
- err = h .updateNginxConf (
202
- ctx ,
203
- cfg ,
204
- )
202
+ err = h .updateNginxConf (ctx , cfg )
205
203
}
206
204
207
205
var nginxReloadRes status.NginxReloadResult
@@ -306,7 +304,10 @@ func (h *eventHandlerImpl) parseAndCaptureEvent(ctx context.Context, logger logr
306
304
}
307
305
308
306
// updateNginxConf updates nginx conf files and reloads nginx.
309
- func (h * eventHandlerImpl ) updateNginxConf (ctx context.Context , conf dataplane.Configuration ) error {
307
+ func (h * eventHandlerImpl ) updateNginxConf (
308
+ ctx context.Context ,
309
+ conf dataplane.Configuration ,
310
+ ) error {
310
311
files := h .cfg .generator .Generate (conf )
311
312
if err := h .cfg .nginxFileMgr .ReplaceFiles (files ); err != nil {
312
313
return fmt .Errorf ("failed to replace NGINX configuration files: %w" , err )
@@ -316,89 +317,114 @@ func (h *eventHandlerImpl) updateNginxConf(ctx context.Context, conf dataplane.C
316
317
return fmt .Errorf ("failed to reload NGINX: %w" , err )
317
318
}
318
319
320
+ // If using NGINX Plus, update upstream servers using the API.
321
+ if err := h .updateUpstreamServers (conf ); err != nil {
322
+ return fmt .Errorf ("failed to update upstream servers: %w" , err )
323
+ }
324
+
319
325
return nil
320
326
}
321
327
322
- // updateUpstreamServers is called only when endpoints have changed. It updates nginx conf files and then:
323
- // - if using NGINX Plus, determines which servers have changed and uses the N+ API to update them;
324
- // - otherwise if not using NGINX Plus, or an error was returned from the API, reloads nginx.
325
- func (h * eventHandlerImpl ) updateUpstreamServers (
326
- ctx context.Context ,
327
- logger logr.Logger ,
328
- conf dataplane.Configuration ,
329
- ) error {
330
- isPlus := h .cfg .nginxRuntimeMgr .IsPlus ()
331
-
332
- files := h .cfg .generator .Generate (conf )
333
- if err := h .cfg .nginxFileMgr .ReplaceFiles (files ); err != nil {
334
- return fmt .Errorf ("failed to replace NGINX configuration files: %w" , err )
328
+ // updateUpstreamServers determines which servers have changed and uses the NGINX Plus API to update them.
329
+ // Only applicable when using NGINX Plus.
330
+ func (h * eventHandlerImpl ) updateUpstreamServers (conf dataplane.Configuration ) error {
331
+ if ! h .cfg .plus {
332
+ return nil
335
333
}
336
334
337
- reload := func () error {
338
- if err := h . cfg . nginxRuntimeMgr . Reload ( ctx , conf . Version ); err != nil {
339
- return fmt .Errorf ("failed to reload NGINX : %w" , err )
340
- }
335
+ prevUpstreams , prevStreamUpstreams , err := h . cfg . nginxRuntimeMgr . GetUpstreams ()
336
+ if err != nil {
337
+ return fmt .Errorf ("failed to get upstreams from API : %w" , err )
338
+ }
341
339
342
- return nil
340
+ type upstream struct {
341
+ name string
342
+ servers []ngxclient.UpstreamServer
343
343
}
344
+ var upstreams []upstream
344
345
345
- if isPlus {
346
- type upstream struct {
347
- name string
348
- servers []ngxclient. UpstreamServer
346
+ for _ , u := range conf . Upstreams {
347
+ confUpstream := upstream {
348
+ name : u . Name ,
349
+ servers : ngxConfig . ConvertEndpoints ( u . Endpoints ),
349
350
}
350
- var upstreams []upstream
351
351
352
- prevUpstreams , err := h . cfg . nginxRuntimeMgr . GetUpstreams ()
353
- if err != nil {
354
- logger . Error ( err , "failed to get upstreams from API, reloading configuration instead" )
355
- return reload ()
352
+ if u , ok := prevUpstreams [ confUpstream . name ]; ok {
353
+ if ! serversEqual ( confUpstream . servers , u . Peers ) {
354
+ upstreams = append ( upstreams , confUpstream )
355
+ }
356
356
}
357
+ }
357
358
358
- for _ , u := range conf . Upstreams {
359
- confUpstream := upstream {
360
- name : u . Name ,
361
- servers : ngxConfig . ConvertEndpoints ( u . Endpoints ),
362
- }
359
+ type streamUpstream struct {
360
+ name string
361
+ servers []ngxclient. StreamUpstreamServer
362
+ }
363
+ var streamUpstreams [] streamUpstream
363
364
364
- if u , ok := prevUpstreams [confUpstream .name ]; ok {
365
- if ! serversEqual (confUpstream .servers , u .Peers ) {
366
- upstreams = append (upstreams , confUpstream )
367
- }
368
- }
365
+ for _ , u := range conf .StreamUpstreams {
366
+ confUpstream := streamUpstream {
367
+ name : u .Name ,
368
+ servers : ngxConfig .ConvertStreamEndpoints (u .Endpoints ),
369
369
}
370
370
371
- var reloadPlus bool
372
- for _ , upstream := range upstreams {
373
- if err := h .cfg .nginxRuntimeMgr .UpdateHTTPServers (upstream .name , upstream .servers ); err != nil {
374
- logger .Error (
375
- err , "couldn't update upstream via the API, reloading configuration instead" ,
376
- "upstreamName" , upstream .name ,
377
- )
378
- reloadPlus = true
371
+ if u , ok := prevStreamUpstreams [confUpstream .name ]; ok {
372
+ if ! serversEqual (confUpstream .servers , u .Peers ) {
373
+ streamUpstreams = append (streamUpstreams , confUpstream )
379
374
}
380
375
}
376
+ }
381
377
382
- if ! reloadPlus {
383
- return nil
378
+ var updateErr error
379
+ for _ , upstream := range upstreams {
380
+ if err := h .cfg .nginxRuntimeMgr .UpdateHTTPServers (upstream .name , upstream .servers ); err != nil {
381
+ updateErr = errors .Join (updateErr , fmt .Errorf (
382
+ "couldn't update upstream %q via the API: %w" , upstream .name , err ))
384
383
}
385
384
}
386
385
387
- return reload ()
386
+ for _ , upstream := range streamUpstreams {
387
+ if err := h .cfg .nginxRuntimeMgr .UpdateStreamServers (upstream .name , upstream .servers ); err != nil {
388
+ updateErr = errors .Join (updateErr , fmt .Errorf (
389
+ "couldn't update stream upstream %q via the API: %w" , upstream .name , err ))
390
+ }
391
+ }
392
+
393
+ return updateErr
388
394
}
389
395
390
- func serversEqual (newServers []ngxclient.UpstreamServer , oldServers []ngxclient.Peer ) bool {
396
+ // serversEqual accepts lists of either UpstreamServer/Peer or StreamUpstreamServer/StreamPeer and determines
397
+ // if the server names within these lists are equal.
398
+ func serversEqual [
399
+ upstreamServer ngxclient.UpstreamServer | ngxclient.StreamUpstreamServer ,
400
+ peer ngxclient.Peer | ngxclient.StreamPeer ,
401
+ ](newServers []upstreamServer , oldServers []peer ) bool {
391
402
if len (newServers ) != len (oldServers ) {
392
403
return false
393
404
}
394
405
406
+ getServerVal := func (T any ) string {
407
+ var server string
408
+ switch t := T .(type ) {
409
+ case ngxclient.UpstreamServer :
410
+ server = t .Server
411
+ case ngxclient.StreamUpstreamServer :
412
+ server = t .Server
413
+ case ngxclient.Peer :
414
+ server = t .Server
415
+ case ngxclient.StreamPeer :
416
+ server = t .Server
417
+ }
418
+ return server
419
+ }
420
+
395
421
diff := make (map [string ]struct {}, len (newServers ))
396
422
for _ , s := range newServers {
397
- diff [s . Server ] = struct {}{}
423
+ diff [getServerVal ( s ) ] = struct {}{}
398
424
}
399
425
400
426
for _ , s := range oldServers {
401
- if _ , ok := diff [s . Server ]; ! ok {
427
+ if _ , ok := diff [getServerVal ( s ) ]; ! ok {
402
428
return false
403
429
}
404
430
}
0 commit comments