-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Block storing invalid pipeline configs caused by nested processors #93425
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,9 @@ | |
import org.elasticsearch.action.ingest.PutPipelineRequest; | ||
import org.elasticsearch.client.internal.node.NodeClient; | ||
import org.elasticsearch.common.bytes.BytesReference; | ||
import org.elasticsearch.common.xcontent.XContentHelper; | ||
import org.elasticsearch.core.Tuple; | ||
import org.elasticsearch.ingest.Pipeline; | ||
import org.elasticsearch.rest.BaseRestHandler; | ||
import org.elasticsearch.rest.RestRequest; | ||
import org.elasticsearch.rest.action.RestToXContentListener; | ||
|
@@ -20,10 +22,12 @@ | |
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
|
||
import static org.elasticsearch.rest.RestRequest.Method.PUT; | ||
|
||
public class RestPutPipelineAction extends BaseRestHandler { | ||
public static final String PROCESSORS_KEY = "processors"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this variable is never used. |
||
|
||
@Override | ||
public List<Route> routes() { | ||
|
@@ -51,6 +55,13 @@ public RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient cl | |
|
||
Tuple<XContentType, BytesReference> sourceTuple = restRequest.contentOrSourceParam(); | ||
PutPipelineRequest request = new PutPipelineRequest(restRequest.param("id"), sourceTuple.v2(), sourceTuple.v1(), ifVersion); | ||
|
||
// check for nested processors in the config | ||
Map<String, Object> config = XContentHelper.convertToMap(request.getSource(), false, request.getXContentType()).v2(); | ||
if (Pipeline.containsNestedProcessors(config)) { | ||
throw new IllegalArgumentException("[processors] contains nested objects but should be a list of single-entry objects"); | ||
} | ||
|
||
request.masterNodeTimeout(restRequest.paramAsTime("master_timeout", request.masterNodeTimeout())); | ||
request.timeout(restRequest.paramAsTime("timeout", request.timeout())); | ||
return channel -> client.admin().cluster().putPipeline(request, new RestToXContentListener<>(channel)); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -211,6 +211,38 @@ public void testParseWithProvidedPipeline() throws Exception { | |
assertThat(actualRequest.pipeline().getProcessors().size(), equalTo(numProcessors)); | ||
} | ||
|
||
public void testParseWithNestedProcessors() throws Exception { | ||
Map<String, Object> requestContent = new HashMap<>(); | ||
Map<String, Object> pipelineConfig = new HashMap<>(); | ||
List<Map<String, Object>> processors = new ArrayList<>(); | ||
Map<String, Object> processorConfig = new HashMap<>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd declare the |
||
List<Map<String, Object>> docs = new ArrayList<>(); | ||
requestContent.put(Fields.DOCS, docs); | ||
String fieldName = randomAlphaOfLengthBetween(1, 10); | ||
String fieldValue = randomAlphaOfLengthBetween(1, 10); | ||
Map<String, Object> doc = new HashMap<>(); | ||
doc.put(Fields.SOURCE, Collections.singletonMap(fieldName, fieldValue)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer |
||
docs.add(doc); | ||
|
||
// first processor | ||
processors.add(Collections.singletonMap("mock_processor", new HashMap<>())); | ||
|
||
// second processor, which is a grok and a date in the same object | ||
processorConfig.put("mock_grok", new HashMap<>()); | ||
processorConfig.put("mock_date", new HashMap<>()); | ||
processors.add(processorConfig); | ||
|
||
pipelineConfig.put("processors", processors); | ||
requestContent.put(Fields.PIPELINE, pipelineConfig); | ||
|
||
// parse and expect failure | ||
Exception e = expectThrows( | ||
IllegalArgumentException.class, | ||
() -> SimulatePipelineRequest.parse(requestContent, false, ingestService, RestApiVersion.current()) | ||
); | ||
assertThat(e.getMessage(), equalTo("[processors] contains nested objects but should be a list of single-entry objects")); | ||
} | ||
|
||
public void testNullPipelineId() { | ||
Map<String, Object> requestContent = new HashMap<>(); | ||
List<Map<String, Object>> docs = new ArrayList<>(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,6 +53,32 @@ public void testCreate() throws Exception { | |
assertThat(pipeline.getProcessors().get(1).getTag(), nullValue()); | ||
} | ||
|
||
public void testContainsNestedProcessors() throws Exception { | ||
// create a pipeline with non-nested processors | ||
Map<String, Object> processorConfig0 = new HashMap<>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd drop |
||
Map<String, Object> processorConfig1 = new HashMap<>(); | ||
processorConfig0.put(ConfigurationUtils.TAG_KEY, "first-processor"); | ||
Map<String, Object> pipelineConfig = new HashMap<>(); | ||
pipelineConfig.put(Pipeline.DESCRIPTION_KEY, "_description"); | ||
pipelineConfig.put(Pipeline.VERSION_KEY, versionString); | ||
if (metadata != null) { | ||
pipelineConfig.put(Pipeline.META_KEY, metadata); | ||
} | ||
pipelineConfig.put(Pipeline.PROCESSORS_KEY, List.of(Map.of("test", processorConfig0), Map.of("test", processorConfig1))); | ||
|
||
assertFalse(Pipeline.containsNestedProcessors(pipelineConfig)); | ||
|
||
// now add one with nested processors | ||
Map<String, Object> processorConfigNested = new HashMap<>(); | ||
processorConfigNested.put("mock_grok", new HashMap<>()); | ||
processorConfigNested.put("mock_date", new HashMap<>()); | ||
pipelineConfig.put( | ||
Pipeline.PROCESSORS_KEY, | ||
List.of(Map.of("test", processorConfig0), Map.of("test", processorConfig1), processorConfigNested) | ||
); | ||
assertTrue(Pipeline.containsNestedProcessors(pipelineConfig)); | ||
} | ||
|
||
public void testCreateWithNoProcessorsField() throws Exception { | ||
Map<String, Object> pipelineConfig = new HashMap<>(); | ||
pipelineConfig.put(Pipeline.DESCRIPTION_KEY, "_description"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this variable is never used.