-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds example plugin for custom ingest processor (#112282)
* Adds example plugin for custom ingest processor Adds an example for creating a plugin with a simple custom ingest processor. The example processor repeats the value of an expected filed in a document, or ignores it if the expected field does not exist. Closes #111539
- Loading branch information
Showing
8 changed files
with
220 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pr: 112282 | ||
summary: Adds example plugin for custom ingest processor | ||
area: Ingest Node | ||
type: enhancement | ||
issues: | ||
- 111539 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
apply plugin: 'elasticsearch.esplugin' | ||
apply plugin: 'elasticsearch.yaml-rest-test' | ||
|
||
esplugin { | ||
name 'custom-processor' | ||
description 'An example plugin showing how to register a custom ingest processor' | ||
classname 'org.elasticsearch.example.customprocessor.ExampleProcessorPlugin' | ||
licenseFile rootProject.file('SSPL-1.0+ELASTIC-LICENSE-2.0.txt') | ||
noticeFile rootProject.file('NOTICE.txt') | ||
} | ||
|
||
dependencies { | ||
yamlRestTestRuntimeOnly "org.apache.logging.log4j:log4j-core:${log4jVersion}" | ||
} |
23 changes: 23 additions & 0 deletions
23
...essor/src/main/java/org/elasticsearch/example/customprocessor/ExampleProcessorPlugin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
package org.elasticsearch.example.customprocessor; | ||
|
||
import org.elasticsearch.ingest.Processor; | ||
import org.elasticsearch.plugins.IngestPlugin; | ||
import org.elasticsearch.plugins.Plugin; | ||
|
||
import java.util.Map; | ||
|
||
public class ExampleProcessorPlugin extends Plugin implements IngestPlugin { | ||
|
||
@Override | ||
public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) { | ||
return Map.of(ExampleRepeatProcessor.TYPE, new ExampleRepeatProcessor.Factory()); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
...essor/src/main/java/org/elasticsearch/example/customprocessor/ExampleRepeatProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package org.elasticsearch.example.customprocessor; | ||
|
||
import org.elasticsearch.ingest.AbstractProcessor; | ||
import org.elasticsearch.ingest.ConfigurationUtils; | ||
import org.elasticsearch.ingest.IngestDocument; | ||
import org.elasticsearch.ingest.Processor; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* Example of adding an ingest processor with a plugin. | ||
*/ | ||
public class ExampleRepeatProcessor extends AbstractProcessor { | ||
public static final String TYPE = "repeat"; | ||
public static final String FIELD_KEY_NAME = "field"; | ||
|
||
private final String field; | ||
|
||
ExampleRepeatProcessor(String tag, String description, String field) { | ||
super(tag, description); | ||
this.field = field; | ||
} | ||
|
||
@Override | ||
public IngestDocument execute(IngestDocument document) { | ||
Object val = document.getFieldValue(field, Object.class, true); | ||
|
||
if (val instanceof String string) { | ||
String repeated = string.concat(string); | ||
document.setFieldValue(field, repeated); | ||
} | ||
return document; | ||
} | ||
|
||
@Override | ||
public String getType() { | ||
return TYPE; | ||
} | ||
|
||
public static class Factory implements Processor.Factory { | ||
|
||
@Override | ||
public ExampleRepeatProcessor create( | ||
Map<String, Processor.Factory> registry, | ||
String tag, | ||
String description, | ||
Map<String, Object> config | ||
) { | ||
String field = ConfigurationUtils.readStringProperty(TYPE, tag, config, FIELD_KEY_NAME); | ||
return new ExampleRepeatProcessor(tag, description, field); | ||
} | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
...java/org/elasticsearch/example/customprocessor/ExampleProcessorClientYamlTestSuiteIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
package org.elasticsearch.example.customprocessor; | ||
|
||
import com.carrotsearch.randomizedtesting.annotations.Name; | ||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; | ||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; | ||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; | ||
|
||
/** | ||
* {@link ExampleProcessorClientYamlTestSuiteIT} executes the plugin's REST API integration tests. | ||
* <p> | ||
* The tests can be executed using the command: ./gradlew :custom-processor:yamlRestTest | ||
* <p> | ||
* This class extends {@link ESClientYamlSuiteTestCase}, which takes care of parsing the YAML files | ||
* located in the src/yamlRestTest/resources/rest-api-spec/test/ directory and validates them against the | ||
* custom REST API definition files located in src/yamlRestTest/resources/rest-api-spec/api/. | ||
* <p> | ||
* Once validated, {@link ESClientYamlSuiteTestCase} executes the REST tests against a single node | ||
* integration cluster which has the plugin already installed by the Gradle build script. | ||
* </p> | ||
*/ | ||
public class ExampleProcessorClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { | ||
|
||
public ExampleProcessorClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { | ||
super(testCandidate); | ||
} | ||
|
||
@ParametersFactory | ||
public static Iterable<Object[]> parameters() throws Exception { | ||
// The test executes all the test candidates by default | ||
// see ESClientYamlSuiteTestCase.REST_TESTS_SUITE | ||
return ESClientYamlSuiteTestCase.createParameters(); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
...stom-processor/src/yamlRestTest/resources/rest-api-spec/test/customprocessor/10_basic.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
"Custom processor is present": | ||
- do: | ||
ingest.put_pipeline: | ||
id: pipeline1 | ||
body: > | ||
{ | ||
"processors": [ | ||
{ | ||
"repeat" : { | ||
"field": "test" | ||
} | ||
} | ||
] | ||
} | ||
- match: { acknowledged: true } |
59 changes: 59 additions & 0 deletions
59
...sor/src/yamlRestTest/resources/rest-api-spec/test/customprocessor/20_process_document.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
setup: | ||
- do: | ||
ingest.put_pipeline: | ||
id: pipeline1 | ||
body: > | ||
{ | ||
"processors": [ | ||
{ | ||
"repeat" : { | ||
"field": "to_repeat" | ||
} | ||
} | ||
] | ||
} | ||
--- | ||
teardown: | ||
- do: | ||
ingest.delete_pipeline: | ||
id: pipeline1 | ||
ignore: 404 | ||
|
||
- do: | ||
indices.delete: | ||
index: index1 | ||
ignore: 404 | ||
--- | ||
"Process document": | ||
# index a document with field to be processed | ||
- do: | ||
index: | ||
id: doc1 | ||
index: index1 | ||
pipeline: pipeline1 | ||
body: { to_repeat: "foo" } | ||
- match: { result: "created" } | ||
|
||
# validate document is processed | ||
- do: | ||
get: | ||
index: index1 | ||
id: doc1 | ||
- match: { _source: { to_repeat: "foofoo" } } | ||
--- | ||
"Does not process document without field": | ||
# index a document without field to be processed | ||
- do: | ||
index: | ||
id: doc1 | ||
index: index1 | ||
pipeline: pipeline1 | ||
body: { field1: "foo" } | ||
- match: { result: "created" } | ||
|
||
# validate document is not processed | ||
- do: | ||
get: | ||
index: index1 | ||
id: doc1 | ||
- match: { _source: { field1: "foo" } } |