or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

action-framework.mdclient-apis.mdcluster-management.mdindex-management.mdindex.mdplugin-framework.mdsearch-apis.md

plugin-framework.mddocs/

0

# Plugin Framework

1

2

Extensible plugin system for adding custom functionality including actions, search components, analysis, and storage engines. OpenSearch provides comprehensive extension points throughout the system for building custom plugins and integrations.

3

4

## Capabilities

5

6

### Core Plugin System

7

8

Base plugin architecture and lifecycle management for extending OpenSearch functionality.

9

10

```java { .api }

11

/**

12

* Base plugin class providing extension points for all OpenSearch functionality

13

*/

14

abstract class Plugin implements Closeable {

15

/**

16

* Get plugin description information

17

*/

18

String getDescription();

19

20

/**

21

* Create Guice modules for dependency injection

22

* @return Collection of Guice modules to register

23

*/

24

Collection<Module> createGuiceModules();

25

26

/**

27

* Provide additional settings that should be added to the cluster

28

* @return Settings to add to cluster configuration

29

*/

30

Settings additionalSettings();

31

32

/**

33

* Get list of setting definitions for this plugin

34

* @return List of setting definitions

35

*/

36

List<Setting<?>> getSettings();

37

38

/**

39

* Get list of settings that require keystore access

40

* @return List of secure setting definitions

41

*/

42

List<Setting<?>> getSecureSettings();

43

44

/**

45

* Called when plugin is closed during shutdown

46

*/

47

void close() throws IOException;

48

49

/**

50

* Get plugin classloader for loading plugin resources

51

*/

52

ClassLoader getPluginClassLoader();

53

}

54

55

/**

56

* Plugin information container with metadata and dependencies

57

*/

58

class PluginInfo implements Streamable {

59

/**

60

* Create plugin info

61

* @param name Plugin name

62

* @param description Plugin description

63

* @param version Plugin version

64

* @param classname Main plugin class name

65

* @param hasNativeController Whether plugin has native controller

66

*/

67

PluginInfo(String name, String description, String version, String classname,

68

boolean hasNativeController);

69

70

/**

71

* Get plugin name

72

*/

73

String getName();

74

75

/**

76

* Get plugin description

77

*/

78

String getDescription();

79

80

/**

81

* Get plugin version

82

*/

83

String getVersion();

84

85

/**

86

* Get main plugin class name

87

*/

88

String getClassname();

89

90

/**

91

* Check if plugin has native controller

92

*/

93

boolean hasNativeController();

94

95

/**

96

* Get OpenSearch version compatibility

97

*/

98

String getOpenSearchVersion();

99

100

/**

101

* Get Java version requirement

102

*/

103

String getJavaVersion();

104

}

105

106

/**

107

* Service for managing plugin lifecycle and registration

108

*/

109

class PluginsService {

110

/**

111

* Create plugins service with configuration

112

* @param settings OpenSearch settings

113

* @param modulesDirectory Modules directory path

114

* @param pluginsDirectory Plugins directory path

115

* @param classpathPlugins Classpath plugin classes

116

*/

117

PluginsService(Settings settings, Path modulesDirectory, Path pluginsDirectory,

118

Collection<Class<? extends Plugin>> classpathPlugins);

119

120

/**

121

* Get all loaded plugins

122

*/

123

List<Tuple<PluginInfo, Plugin>> plugins();

124

125

/**

126

* Get plugins filtered by type

127

* @param type Plugin interface class

128

*/

129

<T> List<T> filterPlugins(Class<T> type);

130

131

/**

132

* Get plugin info by name

133

* @param name Plugin name

134

*/

135

PluginInfo getPluginInfo(String name);

136

137

/**

138

* Check if plugin is loaded

139

* @param name Plugin name

140

*/

141

boolean isPluginLoaded(String name);

142

}

143

```

144

145

### Action Plugin Interface

146

147

Plugin interface for adding custom actions and REST endpoints to OpenSearch.

148

149

```java { .api }

150

/**

151

* Plugin interface for providing custom actions and REST handlers

152

*/

153

interface ActionPlugin {

154

/**

155

* Get list of action handlers provided by this plugin

156

* @return List of action handler registrations

157

*/

158

List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions();

159

160

/**

161

* Get list of REST handlers provided by this plugin

162

* @param settings Cluster settings

163

* @param restController REST controller for registration

164

* @param clusterSettings Cluster settings manager

165

* @param indexScopedSettings Index-scoped settings manager

166

* @param settingsFilter Settings filter for security

167

* @param indexNameExpressionResolver Index name pattern resolver

168

* @param nodesInCluster Supplier for cluster nodes information

169

* @return List of REST handler implementations

170

*/

171

List<RestHandler> getRestHandlers(Settings settings, RestController restController,

172

ClusterSettings clusterSettings, IndexScopedSettings indexScopedSettings,

173

SettingsFilter settingsFilter, IndexNameExpressionResolver indexNameExpressionResolver,

174

Supplier<DiscoveryNodes> nodesInCluster);

175

176

/**

177

* Get list of action filters for intercepting requests

178

* @return List of action filter implementations

179

*/

180

default List<ActionFilter> getActionFilters() {

181

return Collections.emptyList();

182

}

183

184

/**

185

* Get list of task headers that should be preserved across requests

186

* @return Collection of header names to preserve

187

*/

188

default Collection<String> getTaskHeaders() {

189

return Collections.emptyList();

190

}

191

}

192

193

/**

194

* Registration container for action handlers

195

*/

196

class ActionHandler<Request extends ActionRequest, Response extends ActionResponse> {

197

/**

198

* Create action handler registration

199

* @param action Action type definition

200

* @param transportAction Transport action implementation class

201

*/

202

ActionHandler(ActionType<Response> action,

203

Class<? extends TransportAction<Request, Response>> transportAction);

204

205

/**

206

* Create action handler with support actions

207

* @param action Action type definition

208

* @param transportAction Transport action implementation class

209

* @param supportTransportActions Additional support action classes

210

*/

211

ActionHandler(ActionType<Response> action,

212

Class<? extends TransportAction<Request, Response>> transportAction,

213

Class<?>... supportTransportActions);

214

215

/**

216

* Get action type

217

*/

218

ActionType<Response> getAction();

219

220

/**

221

* Get transport action class

222

*/

223

Class<? extends TransportAction<Request, Response>> getTransportAction();

224

225

/**

226

* Get support transport action classes

227

*/

228

Class<?>[] getSupportTransportActions();

229

}

230

231

/**

232

* Base class for REST request handlers

233

*/

234

abstract class BaseRestHandler implements RestHandler {

235

/**

236

* Get routes supported by this handler

237

* @return List of route definitions

238

*/

239

abstract List<Route> routes();

240

241

/**

242

* Handle REST request

243

* @param request REST request

244

* @param channel Response channel

245

* @param client OpenSearch client

246

*/

247

abstract RestChannelConsumer prepareRequest(RestRequest request, NodeClient client)

248

throws IOException;

249

250

/**

251

* Check if request can be handled without content

252

*/

253

protected boolean canTripCircuitBreaker() {

254

return true;

255

}

256

257

/**

258

* Check if handler supports working with content streams

259

*/

260

protected boolean supportsContentStream() {

261

return false;

262

}

263

}

264

```

265

266

### Search Plugin Interface

267

268

Plugin interface for extending search functionality with custom queries, aggregations, and processors.

269

270

```java { .api }

271

/**

272

* Plugin interface for extending search functionality

273

*/

274

interface SearchPlugin {

275

/**

276

* Get custom query builders provided by this plugin

277

* @return List of query builder registrations

278

*/

279

default List<QuerySpec<?>> getQueries() {

280

return Collections.emptyList();

281

}

282

283

/**

284

* Get custom aggregation builders provided by this plugin

285

* @return List of aggregation builder registrations

286

*/

287

default List<AggregationSpec> getAggregations() {

288

return Collections.emptyList();

289

}

290

291

/**

292

* Get custom pipeline aggregations provided by this plugin

293

* @return List of pipeline aggregation registrations

294

*/

295

default List<PipelineAggregationSpec> getPipelineAggregations() {

296

return Collections.emptyList();

297

}

298

299

/**

300

* Get custom function score functions provided by this plugin

301

* @return List of score function registrations

302

*/

303

default List<ScoreFunctionSpec<?>> getScoreFunctions() {

304

return Collections.emptyList();

305

}

306

307

/**

308

* Get custom significance heuristics provided by this plugin

309

* @return List of significance heuristic registrations

310

*/

311

default List<SignificanceHeuristicSpec<?>> getSignificanceHeuristics() {

312

return Collections.emptyList();

313

}

314

315

/**

316

* Get custom MovAvg models provided by this plugin

317

* @return List of moving average model registrations

318

*/

319

default List<MovAvgModelSpec> getMovingAverageModels() {

320

return Collections.emptyList();

321

}

322

323

/**

324

* Get custom fetch sub-phases provided by this plugin

325

* @return List of fetch sub-phase implementations

326

*/

327

default List<FetchSubPhase> getFetchSubPhases(FetchPhaseConstructionContext context) {

328

return Collections.emptyList();

329

}

330

331

/**

332

* Get custom search extensions provided by this plugin

333

* @return List of search extension implementations

334

*/

335

default List<SearchExtension> getSearchExtensions() {

336

return Collections.emptyList();

337

}

338

}

339

340

/**

341

* Query builder specification for plugin registration

342

*/

343

class QuerySpec<T extends QueryBuilder> implements NamedWriteable.Entry<QueryBuilder> {

344

/**

345

* Create query spec

346

* @param name Query name for parsing

347

* @param reader Reader function for deserialization

348

* @param parser Parser function for XContent parsing

349

*/

350

QuerySpec(String name, Writeable.Reader<T> reader, CheckedFunction<XContentParser, T, IOException> parser);

351

352

/**

353

* Get query name

354

*/

355

String getName();

356

357

/**

358

* Get query class

359

*/

360

Class<T> getQueryClass();

361

}

362

363

/**

364

* Aggregation specification for plugin registration

365

*/

366

class AggregationSpec implements NamedWriteable.Entry<AggregationBuilder> {

367

/**

368

* Create aggregation spec

369

* @param name Aggregation name

370

* @param reader Reader function for deserialization

371

* @param parser Parser function for XContent parsing

372

*/

373

AggregationSpec(String name, Writeable.Reader<? extends AggregationBuilder> reader,

374

AggregationParser parser);

375

376

/**

377

* Get aggregation name

378

*/

379

String getName();

380

381

/**

382

* Get aggregation builder class

383

*/

384

Class<? extends AggregationBuilder> getBuilderClass();

385

}

386

```

387

388

### Analysis Plugin Interface

389

390

Plugin interface for providing custom text analysis components including analyzers, tokenizers, and filters.

391

392

```java { .api }

393

/**

394

* Plugin interface for providing text analysis components

395

*/

396

interface AnalysisPlugin {

397

/**

398

* Get custom analyzers provided by this plugin

399

* @return Map of analyzer name to analyzer provider

400

*/

401

default Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getAnalyzers() {

402

return Collections.emptyMap();

403

}

404

405

/**

406

* Get custom character filters provided by this plugin

407

* @return Map of char filter name to char filter provider

408

*/

409

default Map<String, AnalysisProvider<CharFilterFactory>> getCharFilters() {

410

return Collections.emptyMap();

411

}

412

413

/**

414

* Get custom tokenizers provided by this plugin

415

* @return Map of tokenizer name to tokenizer provider

416

*/

417

default Map<String, AnalysisProvider<TokenizerFactory>> getTokenizers() {

418

return Collections.emptyMap();

419

}

420

421

/**

422

* Get custom token filters provided by this plugin

423

* @return Map of token filter name to token filter provider

424

*/

425

default Map<String, AnalysisProvider<TokenFilterFactory>> getTokenFilters() {

426

return Collections.emptyMap();

427

}

428

429

/**

430

* Get custom hunspell dictionaries provided by this plugin

431

* @return Map of language to hunspell dictionary

432

*/

433

default Map<String, Dictionary> getHunspellDictionaries() {

434

return Collections.emptyMap();

435

}

436

437

/**

438

* Get custom normalizers provided by this plugin

439

* @return Map of normalizer name to normalizer provider

440

*/

441

default Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getNormalizers() {

442

return Collections.emptyMap();

443

}

444

}

445

446

/**

447

* Provider interface for analysis components

448

*/

449

interface AnalysisProvider<T> {

450

/**

451

* Create analysis component instance

452

* @param indexSettings Index settings context

453

* @param environment Plugin environment

454

* @param name Component name

455

* @param settings Component settings

456

*/

457

T get(IndexSettings indexSettings, Environment environment, String name, Settings settings);

458

}

459

460

/**

461

* Factory interface for creating analyzers

462

*/

463

interface AnalyzerProvider<T extends Analyzer> extends Closeable {

464

/**

465

* Get analyzer instance

466

*/

467

T get();

468

469

/**

470

* Close analyzer and release resources

471

*/

472

void close();

473

}

474

475

/**

476

* Factory interface for creating character filters

477

*/

478

interface CharFilterFactory {

479

/**

480

* Get character filter name

481

*/

482

String name();

483

484

/**

485

* Create character filter reader

486

* @param reader Input character reader

487

*/

488

Reader create(Reader reader);

489

}

490

491

/**

492

* Factory interface for creating tokenizers

493

*/

494

interface TokenizerFactory {

495

/**

496

* Create tokenizer instance

497

*/

498

Tokenizer create();

499

}

500

501

/**

502

* Factory interface for creating token filters

503

*/

504

interface TokenFilterFactory {

505

/**

506

* Create token filter instance

507

* @param tokenStream Input token stream

508

*/

509

TokenStream create(TokenStream tokenStream);

510

}

511

```

512

513

### Mapper Plugin Interface

514

515

Plugin interface for providing custom field mappers and data type support.

516

517

```java { .api }

518

/**

519

* Plugin interface for providing custom field mappers

520

*/

521

interface MapperPlugin {

522

/**

523

* Get custom field mappers provided by this plugin

524

* @return Map of type name to mapper parser

525

*/

526

Map<String, Mapper.TypeParser> getMappers();

527

528

/**

529

* Get custom metadata mappers provided by this plugin

530

* @return Map of name to metadata mapper parser

531

*/

532

default Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {

533

return Collections.emptyMap();

534

}

535

536

/**

537

* Get custom field filter provided by this plugin

538

* @return Field filter implementation

539

*/

540

default Function<String, Predicate<String>> getFieldFilter() {

541

return MapperPlugin.NOOP_FIELD_FILTER;

542

}

543

544

/**

545

* No-op field filter that allows all fields

546

*/

547

Function<String, Predicate<String>> NOOP_FIELD_FILTER = index -> field -> true;

548

}

549

550

/**

551

* Base mapper for field mapping implementations

552

*/

553

abstract class Mapper implements Streamable {

554

/**

555

* Get mapper name

556

*/

557

String name();

558

559

/**

560

* Get mapper type name

561

*/

562

abstract String typeName();

563

564

/**

565

* Merge with another mapper

566

* @param mergeWith Mapper to merge with

567

* @param mergeReason Reason for merge operation

568

*/

569

abstract Mapper merge(Mapper mergeWith, MergeReason mergeReason);

570

571

/**

572

* Validate field mapping configuration

573

* @param indexSettings Index settings context

574

*/

575

abstract void validate(MappingLookup mappers, IndexSettings indexSettings);

576

577

/**

578

* Type parser interface for creating mapper instances

579

*/

580

interface TypeParser {

581

/**

582

* Parse mapper configuration and create mapper builder

583

* @param name Field name

584

* @param node Mapping configuration

585

* @param parserContext Parser context

586

*/

587

Builder parse(String name, Map<String, Object> node, ParserContext parserContext)

588

throws MapperParsingException;

589

}

590

591

/**

592

* Builder interface for constructing mappers

593

*/

594

abstract static class Builder {

595

/**

596

* Build mapper instance

597

* @param context Build context

598

*/

599

abstract Mapper build(ContentPath contentPath, MapperBuilderContext context);

600

}

601

}

602

```

603

604

### Ingest Plugin Interface

605

606

Plugin interface for providing custom ingest processors for document processing pipelines.

607

608

```java { .api }

609

/**

610

* Plugin interface for providing custom ingest processors

611

*/

612

interface IngestPlugin {

613

/**

614

* Get custom processors provided by this plugin

615

* @param processorFactories Existing processor factories

616

* @return Map of processor name to processor factory

617

*/

618

Map<String, Processor.Factory> getProcessors(Processor.Parameters processorFactories);

619

620

/**

621

* Get additional ingest capabilities provided by this plugin

622

* @return List of ingest capability extensions

623

*/

624

default List<IngestCapability> getIngestCapabilities() {

625

return Collections.emptyList();

626

}

627

}

628

629

/**

630

* Base processor interface for document processing in ingest pipelines

631

*/

632

interface Processor {

633

/**

634

* Get processor type name

635

*/

636

String getType();

637

638

/**

639

* Get processor tag for identification

640

*/

641

String getTag();

642

643

/**

644

* Get processor description

645

*/

646

String getDescription();

647

648

/**

649

* Execute processor on ingest document

650

* @param ingestDocument Document to process

651

* @return Processed ingest document

652

*/

653

IngestDocument execute(IngestDocument ingestDocument) throws Exception;

654

655

/**

656

* Factory interface for creating processor instances

657

*/

658

interface Factory {

659

/**

660

* Create processor instance

661

* @param processorFactories Available processor factories

662

* @param tag Processor tag

663

* @param description Processor description

664

* @param config Processor configuration

665

*/

666

Processor create(Map<String, Factory> processorFactories, String tag,

667

String description, Map<String, Object> config) throws Exception;

668

}

669

670

/**

671

* Parameters container for processor factory access

672

*/

673

class Parameters {

674

/**

675

* Get environment configuration

676

*/

677

public Environment env;

678

679

/**

680

* Get script service for script processors

681

*/

682

public ScriptService scriptService;

683

684

/**

685

* Get analysis registry for text analysis

686

*/

687

public AnalysisRegistry analysisRegistry;

688

689

/**

690

* Get thread pool for async operations

691

*/

692

public ThreadPool threadPool;

693

694

/**

695

* Get ingest service reference

696

*/

697

public IngestService ingestService;

698

}

699

}

700

701

/**

702

* Abstract base class for simple processor implementations

703

*/

704

abstract class AbstractProcessor implements Processor {

705

/**

706

* Create abstract processor

707

* @param tag Processor tag

708

* @param description Processor description

709

*/

710

protected AbstractProcessor(String tag, String description);

711

712

/**

713

* Get processor tag

714

*/

715

String getTag();

716

717

/**

718

* Get processor description

719

*/

720

String getDescription();

721

}

722

```

723

724

### Repository Plugin Interface

725

726

Plugin interface for providing custom snapshot repository implementations.

727

728

```java { .api }

729

/**

730

* Plugin interface for providing custom snapshot repositories

731

*/

732

interface RepositoryPlugin {

733

/**

734

* Get custom repository types provided by this plugin

735

* @return Map of repository type to repository factory

736

*/

737

Map<String, Repository.Factory> getRepositories(Environment env, NamedXContentRegistry namedXContentRegistry,

738

ClusterService clusterService, BigArrays bigArrays, RecoverySettings recoverySettings);

739

740

/**

741

* Get custom repository cleanup extensions

742

* @return Map of repository type to cleanup extensions

743

*/

744

default Map<String, Repository.Factory> getInternalRepositories(Environment env,

745

NamedXContentRegistry namedXContentRegistry, ClusterService clusterService,

746

RecoverySettings recoverySettings) {

747

return Collections.emptyMap();

748

}

749

}

750

751

/**

752

* Base repository interface for snapshot storage implementations

753

*/

754

interface Repository extends Closeable {

755

/**

756

* Get repository metadata

757

*/

758

RepositoryMetadata getMetadata();

759

760

/**

761

* Initialize repository with cluster state

762

* @param clusterState Current cluster state

763

*/

764

void initializeSnapshot(SnapshotId snapshotId, List<IndexId> indices, Metadata metadata);

765

766

/**

767

* Finalize snapshot creation

768

* @param finalizeContext Snapshot finalization context

769

*/

770

SnapshotInfo finalizeSnapshot(FinalizeSnapshotContext finalizeContext);

771

772

/**

773

* Delete snapshot from repository

774

* @param snapshotId Snapshot to delete

775

* @param repositoryStateId Repository state version

776

* @param writeShardGens Whether to write shard generation files

777

* @param listener Completion callback

778

*/

779

void deleteSnapshots(Collection<SnapshotId> snapshotIds, long repositoryStateId,

780

boolean writeShardGens, ActionListener<RepositoryData> listener);

781

782

/**

783

* Factory interface for creating repository instances

784

*/

785

interface Factory {

786

/**

787

* Create repository instance

788

* @param metadata Repository metadata configuration

789

*/

790

Repository create(RepositoryMetadata metadata) throws Exception;

791

792

/**

793

* Create repository instance with recovery settings

794

* @param metadata Repository metadata configuration

795

* @param typeLookup Type lookup for deserialization

796

*/

797

Repository create(RepositoryMetadata metadata, Function<String, Repository.Factory> typeLookup)

798

throws Exception;

799

}

800

}

801

```

802

803

## Usage Examples

804

805

### Creating a Custom Action Plugin

806

807

```java

808

import org.opensearch.plugins.ActionPlugin;

809

import org.opensearch.plugins.Plugin;

810

import org.opensearch.rest.BaseRestHandler;

811

import org.opensearch.rest.RestRequest;

812

import org.opensearch.client.node.NodeClient;

813

814

/**

815

* Example plugin that provides a custom action and REST endpoint

816

*/

817

public class CustomActionPlugin extends Plugin implements ActionPlugin {

818

819

@Override

820

public List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions() {

821

return List.of(

822

new ActionHandler<>(CustomAction.INSTANCE, TransportCustomAction.class)

823

);

824

}

825

826

@Override

827

public List<RestHandler> getRestHandlers(Settings settings, RestController restController,

828

ClusterSettings clusterSettings, IndexScopedSettings indexScopedSettings,

829

SettingsFilter settingsFilter, IndexNameExpressionResolver indexNameExpressionResolver,

830

Supplier<DiscoveryNodes> nodesInCluster) {

831

832

return List.of(new RestCustomHandler());

833

}

834

}

835

836

/**

837

* Custom action type definition

838

*/

839

public class CustomAction extends ActionType<CustomResponse> {

840

public static final CustomAction INSTANCE = new CustomAction();

841

public static final String NAME = "cluster:admin/custom_action";

842

843

private CustomAction() {

844

super(NAME, CustomResponse::new);

845

}

846

}

847

848

/**

849

* Custom action request

850

*/

851

public class CustomRequest extends ActionRequest {

852

private String parameter;

853

854

public CustomRequest(String parameter) {

855

this.parameter = parameter;

856

}

857

858

public String getParameter() {

859

return parameter;

860

}

861

862

@Override

863

public ActionRequestValidationException validate() {

864

if (parameter == null || parameter.isEmpty()) {

865

ActionRequestValidationException validationException = new ActionRequestValidationException();

866

validationException.addValidationError("parameter cannot be null or empty");

867

return validationException;

868

}

869

return null;

870

}

871

}

872

873

/**

874

* Custom action response

875

*/

876

public class CustomResponse extends ActionResponse {

877

private String result;

878

879

public CustomResponse(String result) {

880

this.result = result;

881

}

882

883

public String getResult() {

884

return result;

885

}

886

887

@Override

888

public void writeTo(StreamOutput out) throws IOException {

889

out.writeString(result);

890

}

891

}

892

893

/**

894

* REST handler for custom action

895

*/

896

public class RestCustomHandler extends BaseRestHandler {

897

898

@Override

899

public List<Route> routes() {

900

return List.of(

901

new Route(GET, "/_custom/{param}"),

902

new Route(POST, "/_custom/{param}")

903

);

904

}

905

906

@Override

907

public String getName() {

908

return "custom_action_handler";

909

}

910

911

@Override

912

protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {

913

String param = request.param("param");

914

CustomRequest customRequest = new CustomRequest(param);

915

916

return channel -> client.execute(CustomAction.INSTANCE, customRequest,

917

new RestToXContentListener<>(channel));

918

}

919

}

920

```

921

922

### Creating a Custom Query Plugin

923

924

```java

925

import org.opensearch.plugins.SearchPlugin;

926

import org.opensearch.index.query.QueryBuilder;

927

import org.opensearch.index.query.AbstractQueryBuilder;

928

929

/**

930

* Plugin providing a custom query builder

931

*/

932

public class CustomQueryPlugin extends Plugin implements SearchPlugin {

933

934

@Override

935

public List<QuerySpec<?>> getQueries() {

936

return List.of(

937

new QuerySpec<>(

938

CustomQueryBuilder.NAME,

939

CustomQueryBuilder::new,

940

CustomQueryBuilder::fromXContent

941

)

942

);

943

}

944

}

945

946

/**

947

* Custom query builder implementation

948

*/

949

public class CustomQueryBuilder extends AbstractQueryBuilder<CustomQueryBuilder> {

950

public static final String NAME = "custom_query";

951

952

private final String field;

953

private final String value;

954

private final float boost;

955

956

public CustomQueryBuilder(String field, String value) {

957

this.field = field;

958

this.value = value;

959

this.boost = 1.0f;

960

}

961

962

public CustomQueryBuilder boost(float boost) {

963

return new CustomQueryBuilder(field, value).boost(boost);

964

}

965

966

@Override

967

protected void doWriteTo(StreamOutput out) throws IOException {

968

out.writeString(field);

969

out.writeString(value);

970

out.writeFloat(boost);

971

}

972

973

@Override

974

protected void doXContent(XContentBuilder builder, Params params) throws IOException {

975

builder.startObject(NAME);

976

builder.startObject(field);

977

builder.field("value", value);

978

if (boost != 1.0f) {

979

builder.field("boost", boost);

980

}

981

builder.endObject();

982

builder.endObject();

983

}

984

985

public static CustomQueryBuilder fromXContent(XContentParser parser) throws IOException {

986

// Implementation for parsing from XContent

987

// ... parsing logic here

988

return new CustomQueryBuilder("field", "value");

989

}

990

991

@Override

992

protected Query doToQuery(QueryShardContext context) throws IOException {

993

// Convert to Lucene query

994

return new TermQuery(new Term(field, value));

995

}

996

997

@Override

998

protected boolean doEquals(CustomQueryBuilder other) {

999

return Objects.equals(field, other.field) &&

1000

Objects.equals(value, other.value) &&

1001

Float.compare(boost, other.boost) == 0;

1002

}

1003

1004

@Override

1005

protected int doHashCode() {

1006

return Objects.hash(field, value, boost);

1007

}

1008

1009

@Override

1010

public String getWriteableName() {

1011

return NAME;

1012

}

1013

}

1014

```

1015

1016

### Creating a Custom Analysis Plugin

1017

1018

```java

1019

import org.opensearch.plugins.AnalysisPlugin;

1020

import org.opensearch.index.analysis.TokenFilterFactory;

1021

1022

/**

1023

* Plugin providing custom text analysis components

1024

*/

1025

public class CustomAnalysisPlugin extends Plugin implements AnalysisPlugin {

1026

1027

@Override

1028

public Map<String, AnalysisProvider<TokenFilterFactory>> getTokenFilters() {

1029

return Map.of("custom_filter", CustomTokenFilterFactory::new);

1030

}

1031

1032

@Override

1033

public Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getAnalyzers() {

1034

return Map.of("custom_analyzer", CustomAnalyzerProvider::new);

1035

}

1036

}

1037

1038

/**

1039

* Custom token filter factory

1040

*/

1041

public class CustomTokenFilterFactory implements TokenFilterFactory {

1042

private final Settings settings;

1043

1044

public CustomTokenFilterFactory(IndexSettings indexSettings, Environment environment,

1045

String name, Settings settings) {

1046

this.settings = settings;

1047

}

1048

1049

@Override

1050

public String name() {

1051

return "custom_filter";

1052

}

1053

1054

@Override

1055

public TokenStream create(TokenStream tokenStream) {

1056

return new CustomTokenFilter(tokenStream, settings);

1057

}

1058

}

1059

1060

/**

1061

* Custom token filter implementation

1062

*/

1063

public class CustomTokenFilter extends TokenFilter {

1064

private final CharTermAttribute termAttribute;

1065

private final Settings settings;

1066

1067

public CustomTokenFilter(TokenStream input, Settings settings) {

1068

super(input);

1069

this.settings = settings;

1070

this.termAttribute = addAttribute(CharTermAttribute.class);

1071

}

1072

1073

@Override

1074

public boolean incrementToken() throws IOException {

1075

if (input.incrementToken()) {

1076

// Custom token processing logic

1077

String term = termAttribute.toString();

1078

String processed = processTerm(term);

1079

termAttribute.setEmpty().append(processed);

1080

return true;

1081

}

1082

return false;

1083

}

1084

1085

private String processTerm(String term) {

1086

// Custom processing logic

1087

return term.toLowerCase();

1088

}

1089

}

1090

1091

/**

1092

* Custom analyzer provider

1093

*/

1094

public class CustomAnalyzerProvider implements AnalyzerProvider<Analyzer> {

1095

private final Analyzer analyzer;

1096

1097

public CustomAnalyzerProvider(IndexSettings indexSettings, Environment environment,

1098

String name, Settings settings) {

1099

this.analyzer = new CustomAnalyzer(settings);

1100

}

1101

1102

@Override

1103

public Analyzer get() {

1104

return analyzer;

1105

}

1106

1107

@Override

1108

public void close() {

1109

// Cleanup if needed

1110

}

1111

}

1112

```

1113

1114

### Creating a Custom Ingest Processor Plugin

1115

1116

```java

1117

import org.opensearch.plugins.IngestPlugin;

1118

import org.opensearch.ingest.Processor;

1119

import org.opensearch.ingest.AbstractProcessor;

1120

import org.opensearch.ingest.IngestDocument;

1121

1122

/**

1123

* Plugin providing custom ingest processors

1124

*/

1125

public class CustomIngestPlugin extends Plugin implements IngestPlugin {

1126

1127

@Override

1128

public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) {

1129

return Map.of("custom_processor", new CustomProcessorFactory());

1130

}

1131

}

1132

1133

/**

1134

* Factory for creating custom processor instances

1135

*/

1136

public class CustomProcessorFactory implements Processor.Factory {

1137

1138

@Override

1139

public CustomProcessor create(Map<String, Processor.Factory> processorFactories,

1140

String tag, String description, Map<String, Object> config) {

1141

String field = ConfigurationUtils.readStringProperty("custom_processor", tag, config, "field");

1142

String value = ConfigurationUtils.readStringProperty("custom_processor", tag, config, "value");

1143

boolean ignoreMissing = ConfigurationUtils.readBooleanProperty("custom_processor", tag, config,

1144

"ignore_missing", false);

1145

1146

return new CustomProcessor(tag, description, field, value, ignoreMissing);

1147

}

1148

}

1149

1150

/**

1151

* Custom ingest processor implementation

1152

*/

1153

public class CustomProcessor extends AbstractProcessor {

1154

public static final String TYPE = "custom_processor";

1155

1156

private final String field;

1157

private final String value;

1158

private final boolean ignoreMissing;

1159

1160

public CustomProcessor(String tag, String description, String field, String value, boolean ignoreMissing) {

1161

super(tag, description);

1162

this.field = field;

1163

this.value = value;

1164

this.ignoreMissing = ignoreMissing;

1165

}

1166

1167

@Override

1168

public String getType() {

1169

return TYPE;

1170

}

1171

1172

@Override

1173

public IngestDocument execute(IngestDocument ingestDocument) throws Exception {

1174

if (!ingestDocument.hasField(field)) {

1175

if (ignoreMissing) {

1176

return ingestDocument;

1177

} else {

1178

throw new IllegalArgumentException("Field [" + field + "] does not exist");

1179

}

1180

}

1181

1182

// Custom processing logic

1183

String currentValue = ingestDocument.getFieldValue(field, String.class);

1184

String processedValue = processValue(currentValue);

1185

ingestDocument.setFieldValue(field, processedValue);

1186

1187

return ingestDocument;

1188

}

1189

1190

private String processValue(String input) {

1191

// Custom value processing

1192

return input + "_" + value;

1193

}

1194

}

1195

```

1196

1197

## Types

1198

1199

```java { .api }

1200

/**

1201

* Plugin environment providing access to configuration and resources

1202

*/

1203

class Environment {

1204

/**

1205

* Get settings configuration

1206

*/

1207

Settings settings();

1208

1209

/**

1210

* Get config directory path

1211

*/

1212

Path configDir();

1213

1214

/**

1215

* Get plugins directory path

1216

*/

1217

Path pluginsDir();

1218

1219

/**

1220

* Get modules directory path

1221

*/

1222

Path modulesDir();

1223

1224

/**

1225

* Get logs directory path

1226

*/

1227

Path logsDir();

1228

1229

/**

1230

* Get temporary directory path

1231

*/

1232

Path tmpDir();

1233

}

1234

1235

/**

1236

* Route definition for REST handlers

1237

*/

1238

class Route {

1239

/**

1240

* Create route with method and path

1241

* @param method HTTP method

1242

* @param path URL path pattern

1243

*/

1244

Route(RestRequest.Method method, String path);

1245

1246

/**

1247

* Create route with method, path, and deprecation message

1248

* @param method HTTP method

1249

* @param path URL path pattern

1250

* @param deprecationMessage Deprecation warning message

1251

*/

1252

Route(RestRequest.Method method, String path, String deprecationMessage);

1253

1254

/**

1255

* Get HTTP method

1256

*/

1257

RestRequest.Method getMethod();

1258

1259

/**

1260

* Get path pattern

1261

*/

1262

String getPath();

1263

1264

/**

1265

* Get deprecation message

1266

*/

1267

String getDeprecationMessage();

1268

}

1269

1270

/**

1271

* Transport action base class for handling cluster operations

1272

*/

1273

abstract class TransportAction<Request extends ActionRequest, Response extends ActionResponse> {

1274

/**

1275

* Execute action with request and response listener

1276

* @param task Task context

1277

* @param request Action request

1278

* @param listener Response callback

1279

*/

1280

protected abstract void doExecute(Task task, Request request, ActionListener<Response> listener);

1281

1282

/**

1283

* Get action name

1284

*/

1285

String actionName();

1286

1287

/**

1288

* Get transport service

1289

*/

1290

protected TransportService transportService();

1291

1292

/**

1293

* Get cluster service

1294

*/

1295

protected ClusterService clusterService();

1296

}

1297

1298

/**

1299

* Setting definition for plugin configuration

1300

*/

1301

class Setting<T> {

1302

/**

1303

* Create setting with key and default value

1304

* @param key Setting key

1305

* @param defaultValue Default value

1306

* @param parser Value parser function

1307

* @param properties Setting properties

1308

*/

1309

static <T> Setting<T> simpleString(String key, String defaultValue, Property... properties);

1310

1311

/**

1312

* Create integer setting

1313

* @param key Setting key

1314

* @param defaultValue Default integer value

1315

* @param minValue Minimum allowed value

1316

* @param properties Setting properties

1317

*/

1318

static Setting<Integer> intSetting(String key, int defaultValue, int minValue, Property... properties);

1319

1320

/**

1321

* Create boolean setting

1322

* @param key Setting key

1323

* @param defaultValue Default boolean value

1324

* @param properties Setting properties

1325

*/

1326

static Setting<Boolean> boolSetting(String key, boolean defaultValue, Property... properties);

1327

1328

/**

1329

* Get setting key

1330

*/

1331

String getKey();

1332

1333

/**

1334

* Get default value

1335

*/

1336

T getDefault(Settings settings);

1337

1338

/**

1339

* Setting properties enumeration

1340

*/

1341

enum Property {

1342

DYNAMIC, INDEX_SCOPE, CLUSTER_SCOPE, DEPRECATED, FILTERED

1343

}

1344

}

1345

```