Skip to content

Use GetMappingsRequest instead of GetIndexRequest in QueryPlanningTool#4785

Open
owaiskazi19 wants to merge 2 commits intoopensearch-project:mainfrom
owaiskazi19:fix/qpt-use-get-mappings
Open

Use GetMappingsRequest instead of GetIndexRequest in QueryPlanningTool#4785
owaiskazi19 wants to merge 2 commits intoopensearch-project:mainfrom
owaiskazi19:fix/qpt-use-get-mappings

Conversation

@owaiskazi19
Copy link
Copy Markdown
Member

Description

QueryPlanningTool uses GetIndexRequest to retrieve index mappings for query planning, but it only accesses .mappings() from the response. GetIndexRequest requires the indices:admin/get permission, which also exposes index settings, aliases, and defaults — none of which QPT uses.

This PR switches to GetMappingsRequest / GetMappingsResponse, which only requires indices:admin/mappings/get. This:

  • Follows the principle of least privilege
  • Aligns with how knn_full_access and query_assistant_access roles already handle mapping retrieval
  • Enables the ml_full_access role to support Agentic Search (QueryPlanningTool) with the narrower indices:admin/mappings/get permission instead of the broader indices:admin/get

Related Issue

Resolves #4775

Changes

QueryPlanningTool.java:

  • GetIndexRequestGetMappingsRequest
  • GetIndexResponseGetMappingsResponse
  • client.admin().indices().getIndex()client.admin().indices().getMappings()
  • Response handling unchanged — .mappings() returns the same Map<String, MappingMetadata>

QueryPlanningToolTests.java:

  • All mocks updated to use GetMappingsResponse
  • All indicesAdminClient.getIndex()indicesAdminClient.getMappings()

Check List

  • New functionality includes testing
  • New functionality has been documented
    • N/A (internal API change, no user-facing doc change)
  • Commits are signed off as per the DCO using --signoff

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

PR Reviewer Guide 🔍

(Review updated until commit 00b97d2)

Here are some key observations to aid the review process:

🧪 PR contains tests
🔒 No security concerns identified
✅ No TODO sections
🔀 No multiple PR themes
⚡ Recommended focus areas for review

Stale Variable Name

The field getIndexResponse in the test class was renamed from GetIndexResponse type to GetMappingsResponse type, but the variable name getIndexResponse was kept unchanged. This is misleading and could cause confusion during maintenance. It should be renamed to getMappingsResponse or similar to reflect the new type.

private GetMappingsResponse getIndexResponse;
Stale Comment

The comment on line 1512 still says "Mock getIndex to return mappings keyed by multiple concrete indices" — it references the old getIndex method. It should be updated to reference getMappings for accuracy.

// Mock getIndex to return mappings keyed by multiple concrete indices (simulating alias resolution)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

PR Code Suggestions ✨

Latest suggestions up to 00b97d2

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Add missing mappings stub on mocked response

After removing the when(getIndexResponse.indices()).thenReturn(...) stub, the mock
for getIndexResponse.mappings() is never set up in mockGetIndexMapping(). Tests that
call mockGetIndexMapping() and then invoke
actionListenerCaptor.getValue().onResponse(getIndexResponse) will receive null from
getMappingsResponse.mappings(), causing unexpected IllegalStateException failures
instead of exercising the happy path. Add a
when(getIndexResponse.mappings()).thenReturn(...) stub with the expected mapping
data.

ml-algorithms/src/test/java/org/opensearch/ml/engine/tools/QueryPlanningToolTests.java [165-169]

 this.getIndexResponse = mock(GetMappingsResponse.class);
 
     // Create real MappingMetadata with actual source
     String mappingSource = "{\"properties\":{\"title\":{\"type\":\"text\"}}}";
     this.mapping = new MappingMetadata("testIndex", XContentHelper.convertToMap(JsonXContent.jsonXContent, mappingSource, true));
+    Map<String, MappingMetadata> mappingsMap = new HashMap<>();
+    mappingsMap.put("testIndex", this.mapping);
+    when(getIndexResponse.mappings()).thenReturn(mappingsMap);
Suggestion importance[1-10]: 8

__

Why: The old code had when(getIndexResponse.indices()).thenReturn(new String[] { "testIndex" }) which was removed, but no when(getIndexResponse.mappings()).thenReturn(...) stub was added in mockGetIndexMapping(). Without this stub, tests using mockGetIndexMapping() that call onResponse(getIndexResponse) will get null from getMappingsResponse.mappings(), causing unexpected IllegalStateException failures in happy-path tests.

Medium

Previous suggestions

Suggestions up to commit 702c3c0
CategorySuggestion                                                                                                                                    Impact
Possible issue
Remove unsupported method call on new request type

GetMappingsRequest does not have a local() method — that method belongs to
GetIndexRequest. Calling a non-existent method will cause a compilation error.
Remove the .local(false) call since GetMappingsRequest does not support it.

ml-algorithms/src/main/java/org/opensearch/ml/engine/tools/QueryPlanningTool.java [366-370]

 GetMappingsRequest getMappingsRequest = new GetMappingsRequest()
     .indices(indexName)
     .indicesOptions(IndicesOptions.strictExpand())
-    .local(false)
     .clusterManagerNodeTimeout(DEFAULT_CLUSTER_MANAGER_NODE_TIMEOUT);
Suggestion importance[1-10]: 8

__

Why: GetMappingsRequest does not have a .local(false) method (that belongs to GetIndexRequest), so this would cause a compilation error. Removing it is necessary for the code to compile correctly.

Medium
Suggestions up to commit 16120a8
CategorySuggestion                                                                                                                                    Impact
Possible issue
Remove unsupported method call on new request type

GetMappingsRequest does not have a local(boolean) method — this method exists on
GetIndexRequest but not on GetMappingsRequest. This will cause a compilation error.
Remove the .local(false) call since it is not supported by GetMappingsRequest.

ml-algorithms/src/main/java/org/opensearch/ml/engine/tools/QueryPlanningTool.java [366-370]

 GetMappingsRequest getMappingsRequest = new GetMappingsRequest()
     .indices(indexName)
     .indicesOptions(IndicesOptions.strictExpand())
-    .local(false)
     .clusterManagerNodeTimeout(DEFAULT_CLUSTER_MANAGER_NODE_TIMEOUT);
Suggestion importance[1-10]: 8

__

Why: GetMappingsRequest does not have a .local(boolean) method like GetIndexRequest does, so this would cause a compilation error. Removing the unsupported .local(false) call is necessary for the code to compile correctly.

Medium
Suggestions up to commit adda5de
CategorySuggestion                                                                                                                                    Impact
Possible issue
Remove unsupported method calls on new request type

GetMappingsRequest does not have a local() method or a clusterManagerNodeTimeout()
method in the same way GetIndexRequest does. These methods may not exist on
GetMappingsRequest, which would cause a compilation error. Verify that these methods
are available on GetMappingsRequest and remove or replace any unsupported method
calls.

ml-algorithms/src/main/java/org/opensearch/ml/engine/tools/QueryPlanningTool.java [366-369]

 GetMappingsRequest getMappingsRequest = new GetMappingsRequest().indices(indexName)
-            .indicesOptions(IndicesOptions.strictExpand())
-            .local(false)
-            .clusterManagerNodeTimeout(DEFAULT_CLUSTER_MANAGER_NODE_TIMEOUT);
+            .indicesOptions(IndicesOptions.strictExpand());
Suggestion importance[1-10]: 7

__

Why: GetMappingsRequest may not support .local() and .clusterManagerNodeTimeout() methods unlike GetIndexRequest, which could cause a compilation error. This is a potentially valid concern about API compatibility that warrants verification.

Medium

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

Persistent review updated to latest commit 16120a8

@owaiskazi19 owaiskazi19 requested a deployment to ml-commons-cicd-env-require-approval April 7, 2026 18:43 — with GitHub Actions Waiting
@owaiskazi19 owaiskazi19 requested a deployment to ml-commons-cicd-env-require-approval April 7, 2026 18:43 — with GitHub Actions Waiting
@owaiskazi19 owaiskazi19 requested a deployment to ml-commons-cicd-env-require-approval April 7, 2026 18:43 — with GitHub Actions Waiting
@owaiskazi19 owaiskazi19 requested a deployment to ml-commons-cicd-env-require-approval April 7, 2026 18:43 — with GitHub Actions Waiting
QueryPlanningTool only needs index mappings but was using GetIndexRequest
which requires the broader indices:admin/get permission. This change
switches to GetMappingsRequest which only requires indices:admin/mappings/get,
following the principle of least privilege and aligning with how other
tools (knn, query_assistant) request mappings.

Signed-off-by: Owais Kazi <owaiskazi19@gmail.com>
@owaiskazi19 owaiskazi19 force-pushed the fix/qpt-use-get-mappings branch from 16120a8 to 702c3c0 Compare April 7, 2026 19:06
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

Persistent review updated to latest commit 702c3c0

Copy link
Copy Markdown
Collaborator

@rithinpullela rithinpullela left a comment

Choose a reason for hiding this comment

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

Thanks for the PR Owais!

@opensearch-project opensearch-project deleted a comment from github-actions bot Apr 8, 2026
@github-actions
Copy link
Copy Markdown

Persistent review updated to latest commit 00b97d2

@owaiskazi19 owaiskazi19 had a problem deploying to ml-commons-cicd-env-require-approval April 10, 2026 18:29 — with GitHub Actions Failure
@owaiskazi19 owaiskazi19 had a problem deploying to ml-commons-cicd-env-require-approval April 10, 2026 18:29 — with GitHub Actions Failure
@owaiskazi19 owaiskazi19 temporarily deployed to ml-commons-cicd-env-require-approval April 10, 2026 18:29 — with GitHub Actions Inactive
@owaiskazi19 owaiskazi19 had a problem deploying to ml-commons-cicd-env-require-approval April 10, 2026 18:29 — with GitHub Actions Error
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.41%. Comparing base (3b174ad) to head (00b97d2).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##               main    #4785   +/-   ##
=========================================
  Coverage     77.41%   77.41%           
- Complexity    11900    11901    +1     
=========================================
  Files           963      963           
  Lines         53310    53309    -1     
  Branches       6500     6500           
=========================================
+ Hits          41268    41269    +1     
- Misses         9287     9289    +2     
+ Partials       2755     2751    -4     
Flag Coverage Δ
ml-commons 77.41% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

Add indices:admin/get and indices:data/read/search permissions to ml_full_access role for Agentic Search

2 participants