Skip to content

Commit c5193ee

Browse files
authored
Prioritise API with api write=on (#1315)
* prioritising API with write access while creating NGINX Context
1 parent b191759 commit c5193ee

File tree

3 files changed

+262
-81
lines changed

3 files changed

+262
-81
lines changed

internal/datasource/config/nginx_config_parser.go

Lines changed: 91 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
93102
func 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

448455
func (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

739757
func (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

Comments
 (0)