@@ -90,6 +90,15 @@ type (
9090 current * crossplane.Directive , apiType string ) []* model.APIDetails
9191)
9292
93+ type createAPIDetailsParams struct {
94+ locationDirectiveName string
95+ address string
96+ path string
97+ caCertLocation string
98+ isSSL bool
99+ writeEnabled bool
100+ }
101+
93102func NewNginxConfigParser (agentConfig * config.Config ) * NginxConfigParser {
94103 return & NginxConfigParser {
95104 agentConfig : agentConfig ,
@@ -294,6 +303,8 @@ func (ncp *NginxConfigParser) createNginxConfigContext(
294303 }
295304 }
296305
306+ nginxConfigContext .PlusAPIs = ncp .sortPlusAPIs (ctx , nginxConfigContext .PlusAPIs )
307+
297308 nginxConfigContext .StubStatus = ncp .FindStubStatusAPI (ctx , nginxConfigContext )
298309 nginxConfigContext .PlusAPI = ncp .FindPlusAPI (ctx , nginxConfigContext )
299310
@@ -401,7 +412,6 @@ func (ncp *NginxConfigParser) crossplaneConfigTraverseAPIDetails(
401412 callback crossplaneTraverseCallbackAPIDetails ,
402413 apiType string ,
403414) []* model.APIDetails {
404- stop := false
405415 var responses []* model.APIDetails
406416
407417 for _ , dir := range root .Parsed {
@@ -410,7 +420,7 @@ func (ncp *NginxConfigParser) crossplaneConfigTraverseAPIDetails(
410420 responses = append (responses , response ... )
411421 continue
412422 }
413- response = traverseAPIDetails (ctx , dir , callback , & stop , apiType )
423+ response = traverseAPIDetails (ctx , dir , callback , apiType )
414424 if response != nil {
415425 responses = append (responses , response ... )
416426 }
@@ -423,26 +433,23 @@ func traverseAPIDetails(
423433 ctx context.Context ,
424434 root * crossplane.Directive ,
425435 callback crossplaneTraverseCallbackAPIDetails ,
426- stop * bool ,
427436 apiType string ,
428437) (response []* model.APIDetails ) {
429- if * stop {
430- return nil
431- }
438+ var collectedResponses []* model.APIDetails
432439
433440 for _ , child := range root .Block {
434- response = callback (ctx , root , child , apiType )
435- if len (response ) > 0 {
436- * stop = true
437- return response
441+ currentResponse := callback (ctx , root , child , apiType )
442+ if len (currentResponse ) > 0 {
443+ collectedResponses = append (collectedResponses , currentResponse ... )
438444 }
439- response = traverseAPIDetails (ctx , child , callback , stop , apiType )
440- if * stop {
441- return response
445+
446+ recursiveResponse := traverseAPIDetails (ctx , child , callback , apiType )
447+ if len (recursiveResponse ) > 0 {
448+ collectedResponses = append (collectedResponses , recursiveResponse ... )
442449 }
443450 }
444451
445- return response
452+ return collectedResponses
446453}
447454
448455func (ncp * NginxConfigParser ) formatMap (directive * crossplane.Directive ) map [string ]string {
@@ -723,11 +730,22 @@ func (ncp *NginxConfigParser) apiDetailsFromLocationDirective(
723730 addresses := ncp .parseAddressFromServerDirective (parent )
724731 path := ncp .parsePathFromLocationDirective (current )
725732
733+ writeEnabled := ncp .isWriteEnabled (locChild )
734+
726735 if locChild .Directive == locationDirectiveName {
727736 for _ , address := range addresses {
737+ params := createAPIDetailsParams {
738+ locationDirectiveName : locationDirectiveName ,
739+ address : address ,
740+ path : path ,
741+ caCertLocation : caCertLocation ,
742+ isSSL : isSSL ,
743+ writeEnabled : writeEnabled ,
744+ }
745+
728746 details = append (
729747 details ,
730- ncp .createAPIDetails (locationDirectiveName , address , path , caCertLocation , isSSL ),
748+ ncp .createAPIDetails (params ),
731749 )
732750 }
733751 }
@@ -737,28 +755,30 @@ func (ncp *NginxConfigParser) apiDetailsFromLocationDirective(
737755}
738756
739757func (ncp * NginxConfigParser ) createAPIDetails (
740- locationDirectiveName , address , path , caCertLocation string , isSSL bool ,
758+ params createAPIDetailsParams ,
741759) (details * model.APIDetails ) {
742- if strings .HasPrefix (address , "unix:" ) {
760+ if strings .HasPrefix (params . address , "unix:" ) {
743761 format := unixStubStatusFormat
744762
745- if locationDirectiveName == plusAPIDirective {
763+ if params . locationDirectiveName == plusAPIDirective {
746764 format = unixPlusAPIFormat
747765 }
748766
749767 details = & model.APIDetails {
750- URL : fmt .Sprintf (format , path ),
751- Listen : address ,
752- Location : path ,
753- Ca : caCertLocation ,
768+ URL : fmt .Sprintf (format , params .path ),
769+ Listen : params .address ,
770+ Location : params .path ,
771+ Ca : params .caCertLocation ,
772+ WriteEnabled : params .writeEnabled ,
754773 }
755774 } else {
756775 details = & model.APIDetails {
757- URL : fmt .Sprintf ("%s://%s%s" , map [bool ]string {true : "https" , false : "http" }[isSSL ],
758- address , path ),
759- Listen : address ,
760- Location : path ,
761- Ca : caCertLocation ,
776+ URL : fmt .Sprintf ("%s://%s%s" , map [bool ]string {true : "https" , false : "http" }[params .isSSL ],
777+ params .address , params .path ),
778+ Listen : params .address ,
779+ Location : params .path ,
780+ Ca : params .caCertLocation ,
781+ WriteEnabled : params .writeEnabled ,
762782 }
763783 }
764784
@@ -912,3 +932,47 @@ func (ncp *NginxConfigParser) isDuplicateFile(nginxConfigContextFiles []*mpi.Fil
912932
913933 return false
914934}
935+
936+ func (ncp * NginxConfigParser ) isWriteEnabled (locChild * crossplane.Directive ) bool {
937+ if locChild .Directive != plusAPIDirective {
938+ return false
939+ }
940+
941+ for _ , arg := range locChild .Args {
942+ if strings .EqualFold (arg , "write=on" ) {
943+ return true
944+ }
945+ }
946+
947+ return false
948+ }
949+
950+ // sort the API endpoints by prioritizing any API that has 'write=on'.
951+ func (ncp * NginxConfigParser ) sortPlusAPIs (ctx context.Context , apis []* model.APIDetails ) []* model.APIDetails {
952+ foundWriteEnabled := false
953+ for _ , api := range apis {
954+ if api .WriteEnabled {
955+ foundWriteEnabled = true
956+ break
957+ }
958+ }
959+
960+ if ! foundWriteEnabled && len (apis ) > 0 {
961+ slog .InfoContext (ctx , "No write-enabled NGINX Plus API found. Defaulting to read-only API" )
962+ return apis
963+ }
964+
965+ slices .SortFunc (apis , func (a , b * model.APIDetails ) int {
966+ if a .WriteEnabled && ! b .WriteEnabled {
967+ return - 1
968+ }
969+
970+ if b .WriteEnabled && ! a .WriteEnabled {
971+ return 1
972+ }
973+
974+ return 0
975+ })
976+
977+ return apis
978+ }
0 commit comments