Skip to content

Conversation

@VirajSalaka
Copy link
Contributor

@VirajSalaka VirajSalaka commented Jan 6, 2026

Purpose

$subject. With this change, we can keep handlers.go file cleaner.

Goals

Describe what solutions this feature or fix introduces to address the problems outlined above.

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI. Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

User stories

Summary of user stories addressed by this change>

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Summary by CodeRabbit

Release Notes

  • Refactor
    • Centralized policy management architecture for API deployments.
    • Enhanced error handling with specific error classifications for deployment operations.
    • Streamlined API configuration update processing with improved policy and topic lifecycle handling.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 6, 2026

Walkthrough

This PR integrates policy management into the gateway controller by centralizing policy-related logic within the APIDeploymentService. The policyManager dependency is threaded through the dependency chain (main entry point → control plane client → API handlers → deployment service), enabling the deployment service to manage policy derivation, updates, and lifecycle alongside API deployments and WebSub topic registration.

Changes

Cohort / File(s) Summary
Dependency Injection Wiring
gateway/gateway-controller/cmd/controller/main.go, gateway/gateway-controller/pkg/controlplane/client.go
Updated control plane client construction to accept and pass policyManager parameter through the dependency chain, enabling policy management integration at service initialization.
API Handlers Refactoring
gateway/gateway-controller/pkg/api/handlers/handlers.go
Centralized policy management by moving policy-related processing from inline handlers into the deployment service. NewAPIServer now wires policyManager into APIDeploymentService. Removed legacy helper functions (buildStoredPolicyFromAPI, convertAPIPolicy) in favor of deployment-service delegation.
Core Policy & Deployment Logic
gateway/gateway-controller/pkg/utils/api_deployment.go
Introduced APIUpdateParams struct for update requests, custom error types (NotFoundError, HandleMismatchError, APIValidationError, etc.), and new methods: UpdateAPIConfiguration, BuildStoredPolicyFromAPI, handleTopicLifecycle, updatePolicyConfiguration, triggerXDSSnapshotUpdate. Extended APIDeploymentService with policyManager field and refactored WebSub topic lifecycle into dedicated flow.
Test Updates
gateway/gateway-controller/pkg/api/handlers/policy_ordering_test.go, gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go
Updated test setup to inject deploymentService and adapted all policy-related calls from inline helpers to deploymentService.BuildStoredPolicyFromAPI. Adjusted NewAPIDeploymentService constructor calls to match new parameter order (policyManager inserted before validator).

Sequence Diagram(s)

sequenceDiagram
    participant Handler as API Handler
    participant DeploymentSvc as APIDeploymentService
    participant PolicyMgr as PolicyManager
    participant TopicMgr as Topic Manager
    participant XDS as XDS Snapshot Manager

    rect rgb(200, 220, 255)
    Note over Handler,XDS: UpdateAPIConfiguration Flow
    end

    Handler->>DeploymentSvc: UpdateAPIConfiguration(params)
    activate DeploymentSvc

    DeploymentSvc->>DeploymentSvc: Parse & Validate Config
    alt Validation Fails
        DeploymentSvc-->>Handler: Error (APIValidationError)
    else Valid
        DeploymentSvc->>DeploymentSvc: Update Store & DB
        
        rect rgb(220, 255, 220)
        Note over DeploymentSvc,TopicMgr: Topic Lifecycle Management
        end
        
        DeploymentSvc->>TopicMgr: handleTopicLifecycle()
        activate TopicMgr
        TopicMgr-->>DeploymentSvc: ✓ Complete
        deactivate TopicMgr
        
        rect rgb(255, 240, 200)
        Note over DeploymentSvc,PolicyMgr: Policy Derivation & Update
        end
        
        DeploymentSvc->>DeploymentSvc: BuildStoredPolicyFromAPI(config)
        DeploymentSvc->>PolicyMgr: updatePolicyConfiguration()
        activate PolicyMgr
        PolicyMgr-->>DeploymentSvc: ✓ Updated
        deactivate PolicyMgr
        
        rect rgb(240, 220, 255)
        Note over DeploymentSvc,XDS: XDS Synchronization
        end
        
        DeploymentSvc->>XDS: triggerXDSSnapshotUpdate()
        activate XDS
        XDS-->>DeploymentSvc: ✓ Refreshed
        deactivate XDS
        
        DeploymentSvc-->>Handler: APIDeploymentResult
    end
    deactivate DeploymentSvc
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • [Fix]: Rebasing Issues #379: Modifies APIDeploymentService construction and NewClient wiring with dependency parameter changes, directly intersecting with this PR's signature updates and dependency injection refactoring.

Suggested reviewers

  • renuka-fernando

Poem

🐰 A manager for policies, wise and true,
Now woven through the services, old and new!
Topics dance in harmony, snapshots gleam,
Our gateway flows as one unified stream. ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is largely incomplete. It includes only a partial Purpose section; all other required sections (Goals, Approach, User stories, Documentation, Automation tests, Security checks, Samples, Related PRs, Test environment) lack substantive content. Complete the missing sections: provide Goals explaining the solutions, Approach describing implementation details, test coverage information, security verification results, and environment details.
Docstring Coverage ⚠️ Warning Docstring coverage is 64.29% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main refactoring objective: moving API update logic to api_deployment.go and reusing methods between createAPI and UpdateAPI.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
gateway/gateway-controller/pkg/utils/api_deployment.go (1)

178-178: Remove debug print statement.

This fmt.Println statement appears to be leftover debug code that should be removed before merging.

🔎 Proposed fix
 	case api.RestApi:
 		apiData, err := apiConfig.Spec.AsAPIConfigData()
-		fmt.Println("APIData: ", apiData)
 		if err != nil {
🤖 Fix all issues with AI Agents
In @gateway/gateway-controller/pkg/utils/api_deployment.go:
- Line 731: BuildStoredPolicyFromAPI currently dereferences s.routerConfig
(e.g., accessing s.routerConfig.GatewayHost and s.routerConfig.VHosts) which can
be nil; add a defensive nil check at the start of BuildStoredPolicyFromAPI (or
before any access in AsyncWebSub/RestApi code paths) to handle a nil
s.routerConfig safely—either return early with appropriate default
behavior/error or use safe defaults for GatewayHost/VHosts when s.routerConfig
== nil so the code in the AsyncWebSub routeKey generation
(xds.GenerateRouteName("POST", apiData.Context, apiData.Version, ch.Path,
s.routerConfig.GatewayHost)) and the RestApi vhost handling never panics.
🧹 Nitpick comments (2)
gateway/gateway-controller/cmd/controller/main.go (1)

428-546: Consider consolidating policy derivation logic.

The derivePolicyFromAPIConfig and convertAPIPolicyToModel functions duplicate logic that now exists in APIDeploymentService.BuildStoredPolicyFromAPI and convertAPIPolicy. Given the PR's goal to centralize policy-related logic in the deployment service, consider reusing deploymentService.BuildStoredPolicyFromAPI during startup instead of maintaining parallel implementations.

This would prevent the two implementations from diverging over time.

🔎 Suggested approach

Create an APIDeploymentService instance for startup policy loading:

// In the policy loading section (around line 199-221)
tempDeploymentService := utils.NewAPIDeploymentService(
    configStore, db, snapshotManager, policyManager, validator, &cfg.GatewayController.Router)

for _, apiConfig := range loadedAPIs {
    if apiConfig.Configuration.Kind == api.RestApi {
        storedPolicy := tempDeploymentService.BuildStoredPolicyFromAPI(apiConfig)
        if storedPolicy != nil {
            if err := policyStore.Set(storedPolicy); err != nil {
                // handle error
            }
        }
    }
}

Then remove the derivePolicyFromAPIConfig and convertAPIPolicyToModel functions.

gateway/gateway-controller/pkg/api/handlers/handlers.go (1)

984-995: Consider consolidating policy management for LLM/MCP handlers.

The LLM and MCP handlers call s.deploymentService.BuildStoredPolicyFromAPI() and s.policyManager.AddPolicy() inline after creation/update, while CreateAPI and UpdateAPI delegate this to s.deploymentService.updatePolicyConfiguration() internally.

For consistency, consider either:

  1. Having all handlers delegate policy management to the deployment service, or
  2. Documenting why the approaches differ (e.g., LLM/MCP use different deployment services that don't handle policies internally).

This is a minor consistency observation rather than a blocking issue.

Also applies to: 1074-1095, 1221-1232, 1311-1332, 1463-1474, 1640-1661

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a5dbad4 and 0168d0a.

📒 Files selected for processing (6)
  • gateway/gateway-controller/cmd/controller/main.go
  • gateway/gateway-controller/pkg/api/handlers/handlers.go
  • gateway/gateway-controller/pkg/api/handlers/policy_ordering_test.go
  • gateway/gateway-controller/pkg/controlplane/client.go
  • gateway/gateway-controller/pkg/utils/api_deployment.go
  • gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-12-06T11:57:08.456Z
Learnt from: BLasan
Repo: wso2/api-platform PR: 140
File: gateway/gateway-controller/pkg/utils/api_deployment.go:88-105
Timestamp: 2025-12-06T11:57:08.456Z
Learning: In the gateway-controller Go codebase (file: gateway/gateway-controller/pkg/utils/api_deployment.go), only the async/websub API kind is currently supported. async/websocket and async/sse API kinds are not yet implemented.

Applied to files:

  • gateway/gateway-controller/pkg/controlplane/client.go
  • gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go
  • gateway/gateway-controller/pkg/api/handlers/handlers.go
  • gateway/gateway-controller/pkg/utils/api_deployment.go
📚 Learning: 2025-11-08T13:06:22.133Z
Learnt from: thivindu
Repo: wso2/api-platform PR: 110
File: platform-api/src/internal/service/api.go:432-476
Timestamp: 2025-11-08T13:06:22.133Z
Learning: In the platform-api Go codebase (file: platform-api/src/internal/service/api.go), the DeployAPIRevision method is designed to automatically create API-gateway associations during deployment if they don't already exist. There is no requirement that associations must pre-exist before deployment; the system checks for existing associations and creates them on-the-fly as needed.

Applied to files:

  • gateway/gateway-controller/pkg/api/handlers/handlers.go
  • gateway/gateway-controller/pkg/api/handlers/policy_ordering_test.go
  • gateway/gateway-controller/pkg/utils/api_deployment.go
📚 Learning: 2025-12-23T10:41:47.584Z
Learnt from: thivindu
Repo: wso2/api-platform PR: 389
File: gateway/gateway-controller/pkg/utils/api_key.go:257-380
Timestamp: 2025-12-23T10:41:47.584Z
Learning: In gateway/gateway-controller/pkg/utils/api_key.go, the RevokeAPIKey method intentionally proceeds with database deletion and xDS policy engine revocation even when the API key is not found in the memory store (apiKey is nil). This is by design to handle partial failure recovery: if a previous revocation attempt removed the key from memory but failed to clean up the database or policy engine, subsequent retries will still perform the cleanup operations to ensure eventual consistency.

Applied to files:

  • gateway/gateway-controller/pkg/api/handlers/handlers.go
📚 Learning: 2025-12-22T16:00:12.851Z
Learnt from: O-sura
Repo: wso2/api-platform PR: 569
File: gateway/policy-engine/internal/analytics/constants.go:100-101
Timestamp: 2025-12-22T16:00:12.851Z
Learning: In gateway/policy-engine/internal/analytics/constants.go, the constant APITypeKey is intentionally named with "Type" terminology (instead of "Kind") to maintain consistency with the analytics publisher platform, which uses "type" rather than "kind". The constant resolves to "x-wso2-api-kind" but the name APITypeKey is kept for cross-platform naming consistency.

Applied to files:

  • gateway/gateway-controller/pkg/api/handlers/handlers.go
🧬 Code graph analysis (4)
gateway/gateway-controller/pkg/controlplane/client.go (2)
gateway/gateway-controller/pkg/policyxds/manager.go (1)
  • PolicyManager (33-37)
gateway/gateway-controller/pkg/utils/api_deployment.go (1)
  • NewAPIDeploymentService (143-161)
gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go (1)
gateway/gateway-controller/pkg/utils/api_deployment.go (1)
  • NewAPIDeploymentService (143-161)
gateway/gateway-controller/pkg/api/handlers/policy_ordering_test.go (4)
gateway/gateway-controller/pkg/config/config.go (1)
  • RouterConfig (171-184)
gateway/gateway-controller/pkg/storage/memory.go (1)
  • NewConfigStore (49-61)
gateway/gateway-controller/pkg/utils/api_deployment.go (1)
  • NewAPIDeploymentService (143-161)
gateway/gateway-controller/pkg/api/handlers/handlers.go (1)
  • APIServer (50-68)
gateway/gateway-controller/cmd/controller/main.go (1)
gateway/gateway-controller/pkg/controlplane/client.go (1)
  • NewClient (111-154)
🔇 Additional comments (12)
gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go (1)

21-21: LGTM!

The NewAPIDeploymentService calls are correctly updated to match the new constructor signature with policyManager as the 4th parameter. Passing nil for policyManager in these WebSub topic registration tests is appropriate since the tests focus on topic lifecycle management rather than policy functionality.

Also applies to: 66-66, 148-148, 252-252

gateway/gateway-controller/cmd/controller/main.go (1)

275-275: LGTM!

The control plane client construction correctly passes policyManager to NewClient. The policyManager may be nil when the policy server is disabled, which is handled gracefully downstream.

gateway/gateway-controller/pkg/api/handlers/policy_ordering_test.go (2)

34-48: LGTM!

The test setup correctly initializes the APIDeploymentService with minimal dependencies needed for BuildStoredPolicyFromAPI. Passing nil for db, snapshotManager, policyManager, and validator is appropriate since the policy building logic only requires routerConfig for vhost resolution.


203-203: LGTM!

All test calls correctly updated to use server.deploymentService.BuildStoredPolicyFromAPI(cfg), aligning with the refactor that centralizes policy construction in the deployment service.

Also applies to: 317-317, 444-444

gateway/gateway-controller/pkg/controlplane/client.go (1)

110-154: LGTM!

The NewClient constructor correctly threads policyManager through to NewAPIDeploymentService. The design is clean - the Client struct doesn't store policyManager directly since it only needs it for the deployment service's policy handling.

gateway/gateway-controller/pkg/api/handlers/handlers.go (2)

84-84: LGTM!

The NewAPIServer correctly wires policyManager into NewAPIDeploymentService, enabling centralized policy handling within the deployment service.


477-543: Well-structured error handling for UpdateAPI.

The UpdateAPI method correctly delegates to deploymentService.UpdateAPIConfiguration and maps all custom error types (NotFoundError, HandleMismatchError, APIValidationError, ParseError, TopicOperationError, ConflictError, DatabaseUnavailableError) to appropriate HTTP status codes. This aligns well with the refactoring goals.

gateway/gateway-controller/pkg/utils/api_deployment.go (5)

57-128: LGTM - Well-designed custom error types.

The custom error types (NotFoundError, HandleMismatchError, APIValidationError, TopicOperationError, ConflictError, ParseError, DatabaseUnavailableError) are well-structured and enable clean HTTP status code mapping in handlers.


381-465: LGTM - Properly synchronized topic lifecycle handling.

The handleTopicLifecycle method correctly uses:

  • sync.WaitGroup for coordinating concurrent operations
  • atomic.AddInt32 for thread-safe error counting
  • Nested goroutines for parallelizing individual topic operations

The error aggregation and reporting is well-implemented.


285-379: LGTM - UpdateAPIConfiguration is well-structured.

The method correctly:

  • Validates handle consistency between URL path and YAML metadata
  • Runs configuration validation
  • Checks for database availability
  • Handles AsyncWebSub topic lifecycle
  • Updates both database and memory store
  • Triggers async xDS and policy updates
  • Returns appropriate typed errors for HTTP status mapping

677-827: LGTM - BuildStoredPolicyFromAPI centralizes policy construction.

The method correctly:

  • Collects API-level policies into a lookup map
  • Handles both AsyncWebsub and RestApi kinds
  • Merges operation-level policies with API-level policies (operation policies take precedence)
  • Generates correct route keys using xds.GenerateRouteName
  • Handles sandbox vhost routing when sandbox upstream is configured
  • Returns nil when no policies exist (avoiding unnecessary policy configurations)

846-887: LGTM - Clean helper methods for policy and xDS management.

The updatePolicyConfiguration and triggerXDSSnapshotUpdate methods cleanly encapsulate:

  • Policy add/remove logic with appropriate logging levels
  • Async xDS snapshot updates with timeout handling

}
}

routeKey := xds.GenerateRouteName("POST", apiData.Context, apiData.Version, ch.Path, s.routerConfig.GatewayHost)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "api_deployment.go" -path "*/gateway-controller/*" | head -5

Repository: wso2/api-platform

Length of output: 117


🏁 Script executed:

find . -name "policy_ordering_test.go" | head -5

Repository: wso2/api-platform

Length of output: 130


🏁 Script executed:

# Find the BuildStoredPolicyFromAPI method
rg -n "BuildStoredPolicyFromAPI" --type=go -B 2 -A 15 | head -100

Repository: wso2/api-platform

Length of output: 10210


🏁 Script executed:

sed -n '681,800p' ./gateway/gateway-controller/pkg/utils/api_deployment.go

Repository: wso2/api-platform

Length of output: 4372


🏁 Script executed:

rg -n "func newTestAPIServer" --type=go -A 20

Repository: wso2/api-platform

Length of output: 2329


🏁 Script executed:

rg -n "type APIDeploymentService struct" --type=go -A 15

Repository: wso2/api-platform

Length of output: 1510


🏁 Script executed:

# Search for all callers of BuildStoredPolicyFromAPI
rg -n "BuildStoredPolicyFromAPI" --type=go

Repository: wso2/api-platform

Length of output: 1742


🏁 Script executed:

rg -n "type APIServer struct" --type=go -A 10

Repository: wso2/api-platform

Length of output: 1173


🏁 Script executed:

# Check NewAPIDeploymentService calls in handlers.go
rg -n "NewAPIDeploymentService" --type=go -B 2 -A 2

Repository: wso2/api-platform

Length of output: 4533


🏁 Script executed:

# Check where APIServer is instantiated
rg -n "NewAPIServer\|&APIServer\{" --type=go -B 2 -A 5

Repository: wso2/api-platform

Length of output: 43


🏁 Script executed:

# Check what the websub tests do - do they call BuildStoredPolicyFromAPI?
sed -n '19,100p' ./gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go

Repository: wso2/api-platform

Length of output: 2385


🏁 Script executed:

# Check if any websub test calls BuildStoredPolicyFromAPI
rg -n "BuildStoredPolicyFromAPI" ./gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go

Repository: wso2/api-platform

Length of output: 43


🏁 Script executed:

# Check what happens when service is created with nil routerConfig in tests - trace the code path
sed -n '1,50p' ./gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go

Repository: wso2/api-platform

Length of output: 1583


🏁 Script executed:

# Check if there's any code that validates/checks routerConfig before calling BuildStoredPolicyFromAPI
rg -n "routerConfig" ./gateway/gateway-controller/pkg/utils/api_deployment.go

Repository: wso2/api-platform

Length of output: 433


🏁 Script executed:

# Check if websub tests ever trigger BuildStoredPolicyFromAPI through any method calls
sed -n '1,300p' ./gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go | grep -E "store.Add|BuildStoredPolicy|DeployAPIConfiguration"

Repository: wso2/api-platform

Length of output: 404


🏁 Script executed:

# Look at the full context of what happens in a websub test to see if it could trigger the issue
sed -n '1,100p' ./gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go

Repository: wso2/api-platform

Length of output: 2985


🏁 Script executed:

# Search for the Add method in storage to see if it calls BuildStoredPolicyFromAPI
rg -n "func.*Add" ./gateway/gateway-controller/pkg/storage/ --type=go -A 5 | head -50

Repository: wso2/api-platform

Length of output: 1574


🏁 Script executed:

# Check if ConfigStore.Add calls any deployment service methods
rg -n "class ConfigStore\|type ConfigStore" ./gateway/gateway-controller/pkg/storage/ --type=go -A 20

Repository: wso2/api-platform

Length of output: 43


🏁 Script executed:

# Look at where BuildStoredPolicyFromAPI is actually called - in handlers and api_deployment
sed -n '840,870p' ./gateway/gateway-controller/pkg/utils/api_deployment.go

Repository: wso2/api-platform

Length of output: 1341


🏁 Script executed:

# Check where updatePolicyConfiguration is called
rg -n "updatePolicyConfiguration" --type=go

Repository: wso2/api-platform

Length of output: 605


🏁 Script executed:

# Verify the full flow - where is updatePolicyConfiguration called from?
rg -n "updatePolicyConfiguration" --type=go -B 3 -A 3

Repository: wso2/api-platform

Length of output: 2067


🏁 Script executed:

# Check where NewAPIServer is called to verify routerConfig is always provided
rg -n "NewAPIServer" --type=go -B 5 -A 5

Repository: wso2/api-platform

Length of output: 2262


🏁 Script executed:

# Check the function signature of NewAPIServer to understand the flow
sed -n '75,105p' ./gateway/gateway-controller/pkg/api/handlers/handlers.go

Repository: wso2/api-platform

Length of output: 1412


🏁 Script executed:

# Check if there's any place where routerConfig could be nil in production paths
rg -n "cfg.GatewayController.Router" --type=go -B 2 -A 2

Repository: wso2/api-platform

Length of output: 3011


🏁 Script executed:

# Check if there are other callers of APIDeploymentService besides main.go and tests
rg -n "NewAPIDeploymentService" --type=go | grep -v test | grep -v "policy_ordering"

Repository: wso2/api-platform

Length of output: 629


🏁 Script executed:

# Let's check what API kinds trigger the code path - does AsyncWebSub go through buildStoredPolicyFromAPI?
# Check if websub tests actually ever create RestApi which uses routerConfig
sed -n '20,80p' ./gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go | grep -A 5 "kind:"

Repository: wso2/api-platform

Length of output: 307


🏁 Script executed:

# Final verification - check if there's any conditional that prevents BuildStoredPolicyFromAPI from being called when routerConfig is nil
sed -n '677,700p' ./gateway/gateway-controller/pkg/utils/api_deployment.go

Repository: wso2/api-platform

Length of output: 1032


🏁 Script executed:

# Verify the websub tests don't actually call BuildStoredPolicyFromAPI - they only call store.Add
rg -n "store.Add\|BuildStoredPolicy" ./gateway/gateway-controller/pkg/utils/websub_topic_registration_test.go

Repository: wso2/api-platform

Length of output: 43


🏁 Script executed:

# Let me verify the complete flow - check updatePolicyConfiguration for any nil guards
sed -n '846,870p' ./gateway/gateway-controller/pkg/utils/api_deployment.go

Repository: wso2/api-platform

Length of output: 1208


🏁 Script executed:

# Also check where DeployAPIConfiguration and UpdateAPIConfiguration are called to understand the actual usage
rg -n "DeployAPIConfiguration\|UpdateAPIConfiguration" --type=go | grep -v "func\|// " | head -20

Repository: wso2/api-platform

Length of output: 43


🏁 Script executed:

# Final check - verify if there's a guard that prevents BuildStoredPolicyFromAPI from running when routerConfig is nil
rg -n "if s.routerConfig" --type=go

Repository: wso2/api-platform

Length of output: 43


🏁 Script executed:

# Check the exact lines 775-776 to confirm the accesses
sed -n '773,778p' ./gateway/gateway-controller/pkg/utils/api_deployment.go

Repository: wso2/api-platform

Length of output: 359


Add nil check for routerConfig in BuildStoredPolicyFromAPI.

The method accesses s.routerConfig.GatewayHost (line 731 for AsyncWebSub) and s.routerConfig.VHosts (lines 775-776 for RestApi) without checking if routerConfig is nil. This will cause a panic if BuildStoredPolicyFromAPI is called when routerConfig is nil, such as in websub_topic_registration_test.go which passes nil for routerConfig.

Add a defensive nil check:

Proposed fix
func (s *APIDeploymentService) BuildStoredPolicyFromAPI(cfg *models.StoredConfig) *models.StoredPolicyConfig {
+	if s.routerConfig == nil {
+		return nil
+	}
 	apiCfg := &cfg.Configuration

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @gateway/gateway-controller/pkg/utils/api_deployment.go around line 731,
BuildStoredPolicyFromAPI currently dereferences s.routerConfig (e.g., accessing
s.routerConfig.GatewayHost and s.routerConfig.VHosts) which can be nil; add a
defensive nil check at the start of BuildStoredPolicyFromAPI (or before any
access in AsyncWebSub/RestApi code paths) to handle a nil s.routerConfig
safely—either return early with appropriate default behavior/error or use safe
defaults for GatewayHost/VHosts when s.routerConfig == nil so the code in the
AsyncWebSub routeKey generation (xds.GenerateRouteName("POST", apiData.Context,
apiData.Version, ch.Path, s.routerConfig.GatewayHost)) and the RestApi vhost
handling never panics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant