- Developing Plugins for OpenSearch
- Building within the OpenSearch Build System
- Updating Documentation
The easiest way to get started authoring a new OpenSearch plugin is to follow instruction in opensearch-project/opensearch-plugin-template-java. See also My First Steps in OpenSearch Plugins.
All OpenSearch plugins require a plugin-descriptor.properties
file. The fields contained in the plugin-descriptor.properties
file are documented here. When using the gradle build system, these fields can be specified in the build.gradle
file and the build system will generate the properties file.
Use opensearchplugin
in build.gradle
to generate a plugin-descriptor.properties
.
opensearchplugin {
name 'opensearch-plugin'
description 'Example OpenSearch plugin'
classname 'org.opensearch.example.Plugin'
}
OpenSearch builds and releases the core engine at the same time as plugins as one monolithic distribution. This is documented in the build workflow. To accommodate this system plugins are required to make build scripts configurable as follows.
- Define the plugin version based on the version of OpenSearch.
- Consume dynamic versions of OpenSearch dependencies with
-Dopensearch.version=
. - Support building
-SNAPSHOT
vs. release artifacts with-Dbuild.snapshot=
, default to always building snapshot. - Prioritize Maven local for dependencies, including OpenSearch.
- Publish Maven checksums.
Do not include version=
in build.properties
. Instead, dynamically define it in build.gradle
. Adjust the version when building a snapshot.
buildscript {
ext {
opensearch_group = "org.opensearch"
opensearch_version = System.getProperty("opensearch.version", "1.1.0-SNAPSHOT")
}
}
allprojects {
group = 'org.opensearch'
version = opensearch_version - "-SNAPSHOT" + ".0"
}
OpenSearch uses a 3-digit versioning scheme while plugins have a 4th free digit for patches. Patch the version number to consume dependencies such as common-utils or job-scheduler.
buildscript {
ext {
// 1.1.0 -> 1.1.0.0, and 1.1.0-SNAPSHOT -> 1.1.0.0-SNAPSHOT
opensearch_build = opensearch_version.replaceAll(/(\.\d)([^\d]*)$/, '$1.0$2')
common_utils_version = System.getProperty("common_utils.version", opensearch_build)
job_scheduler_version = System.getProperty("job_scheduler.version", opensearch_build)
}
}
Use the above versions as follows.
dependencies {
compile "org.opensearch:opensearch:${opensearch_version}"
compile "org.opensearch:common-utils:${common_utils_version}"
compileOnly "org.opensearch:opensearch-job-scheduler-spi:${job_scheduler_version}"
}
OpenSearch SNAPSHOT artifacts are built continuously and made available in AWS OSS Sonatype Maven.
Plugins that depend on OpenSearch artifacts should always consume -SNAPSHOT
artifacts in all branches in their GHA workflows. While it's typical for Java projects to consume snapshot dependencies early and stabilize on released artifacts, OpenSearch builds and releases the core engine at the same time as plugins as one monolithic distribution, thus switching from -SNAPSHOT
to released artifacts is not necessary. This substitution is performed by the build workflow by passing -Dbuild.snapshot=false
into Gradle build.
buildscript {
ext {
opensearch_group = "org.opensearch"
// always default to -SNAPSHOT
opensearch_version = System.getProperty("opensearch.version", "1.1.0-SNAPSHOT")
}
}
ext {
// support -Dbuild.snapshot=false, but default to true
isSnapshot = "true" == System.getProperty("build.snapshot", "true")
}
allprojects {
group = 'org.opensearch'
version = opensearch_version - "-SNAPSHOT" + ".0"
// append -SNAPSHOT when building snapshot, which is the default
if (isSnapshot) {
version += "-SNAPSHOT"
}
}
Note that signed OpenSearch release artifacts are also available in Maven Central for components that don't release with the monolithic distribution.
Plugins must declare the dependencies for the root projects and all sub-projects in the following order. The first two repositories mavenLocal()
and maven(aws.oss.sonatype.org)
are required, while the rest are optional as needed for external dependencies.
repositories {
mavenLocal()
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
...
}
Same applies for dependencies for the build script itself, in-case the buildscript { }
needs to consume the OpenSearch build-tools
artifact.
buildscript {
repositories {
mavenLocal()
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.opensearch.gradle:build-tools:${opensearch_version}"
...
}
}
If your component publishes maven artifacts, use shadow and publish to a local repository at a non default location.
The maven publish plugin used by gradle will not include checksums when publishing to maven local ~/m2/repository
.
publishing {
repositories {
maven {
name = 'staging'
url = "${rootProject.buildDir}/local-staging-repo"
}
}
publications {
shadow(MavenPublication) { publication ->
...
Use ./gradlew publishShadowPublicationToStagingRepository
to produce maven artifacts. When building as part of the monolithic distribution customize scripts/build.sh
to collect maven artifacts. See job-scheduler#71 for an example.
OpenSearch provides a set of custom gradle plugins that avoid boilerplate code for building and testing plugins.
opensearch.pluginzip
is designed to facilitate OpenSearch plugin distributions (ZIPs) to be available as Apache Maven artifacts which can then be fetched as dependency using Apache Maven dependency management. This plugin identifies the OpenSearch plugin ZIP file, the output of bundlePlugin
task and publishes to local Apache Maven repository.
Plugin Code, Plugin META-INF, Plugin Tests, and gradle build script examples used by Plugin Tests.
opensearch.pluginzip
is java based code published into build-tools.- The maven coordinates
groupID
,version
andartifcatID
will be inferred from gradle project properties. (Prior to OpenSearch 2.4 thegroupId
was fixed asorg.openserach.plugin
regardless of actual gradle projectgroup
value or pluginZip publication POM customizations.) - User can also pass custom POM extensions, that will add desired properties to Apache Maven POM file generated during runtime.
- Once the plugin is added to the
build.gradle
asapply plugin: 'opensearch.pluginzip'
, this will add a new custom publish taskpublishPluginZipPublicationToZipStagingRepository
, the purpose of this task is to publish the ZIP distribution to the Apache Maven local repository (file system). - Since OpenSearch 2.4 this plugin internally applies both the 'nebula.maven-base-publish' and 'maven-publish' plugins which means that it is not necessary to explicitly apply these in your project.
- The Apache Maven local artifacts could then be published to Apache Maven central/nexus using CI workflows.
- The plugin will not publish generated JARs (
sourcesJar
,javadocJar
), this is done on purpose to separatejars
andzip
publications.
-
Ensure that the project uses
bundlePlugin
task that comes from existing PublishPlugin../gradlew tasks --all
should listbundlePlugin
. -
Add build-tools dependency to the current gradle project. (If already exists, dont need to re-add again). Example:
buildscript {
ext {
opensearch_version = System.getProperty("opensearch.version", "2.0.0-rc1-SNAPSHOT")
}
repositories {
mavenLocal()
}
dependencies {
classpath "org.opensearch.gradle:build-tools:${opensearch_version}"
}
}
-
Add
apply plugin: 'opensearch.pluginzip'
to the build.gradle file. Once added, this should list the new taskpublishPluginZipPublicationToZipStagingRepository
. -
Run the task
publishPluginZipPublicationToZipStagingRepository
(add it to managed build scriptbuild.sh
)
./gradlew publishPluginZipPublicationToZipStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER
Note: The gradle task responsible to generate the distribution zip should be called first before executing
publishPluginZipPublicationToZipStagingRepository
, as the zip file needs to be generated before publishing. -
To add custom POM extensions to zip publication: Example:
publishing {
publications {
pluginZip(MavenPublication) { publication ->
pom {
name = pluginName
description = pluginDescription
licenses {
license {
name = "The Apache License, Version 2.0"
url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
}
}
developers {
developer {
name = "OpenSearch"
url = "https://github.com/opensearch-project/opensearch-plugin-template-java"
}
}
}
}
}
}
- To run
build
task using./gradlew build
for the entire project without having proper POM reference, addstartParameter.excludedTaskNames=["validatePluginZipPom"]
insettings.gradle
file, this taskvalidatePluginZipPom
is not required if POM is formatted right withname
,description
,licenses
,developers
fields. If these fields not added and executed./gradlew build
would throw an error as
name is missing in [/usr/share/opensearch/git/opensearch-plugin-template-java/build/distributions/rename-unspecified.pom]
description is missing in [/usr/share/opensearch/git/opensearch-plugin-template-java/build/distributions/rename-unspecified.pom]
licenses is empty in [/usr/share/opensearch/git/opensearch-plugin-template-java/build/distributions/rename-unspecified.pom]
developers is empty in [/usr/share/opensearch/git/opensearch-plugin-template-java/build/distributions/rename-unspecified.pom]
- Note: If gradle project already has the setting as shown in step 5, then its not required to add
startParameter.excludedTaskNames=["validatePluginZipPom"]
. This setting is only required when ran./gradlew build
without proper POM reference.
-
Exclude the following tasks in
settings.gradle
file, if the build script exists for the plugin and has the taskspublishToMavenLocal
andpublishAllPublicationsToStagingRepository
, these will also include the taskspublishPluginZipPublicationToMavenLocal
andpublishPluginZipPublicationToStagingRepository
which is not required to be called with this plugin. To exclude add the following insettings.gradle
filestartParameter.excludedTaskNames=["publishPluginZipPublicationToMavenLocal", "publishPluginZipPublicationToStagingRepository"]
Note: If there is a managed
build.sh
file and do not have any publish tasks, then its not required to exclude these tasks, only required if it is calling publish tasks that targetsALL
repos andALL
publications. -
Quick Example: Job-scheduler: build.gradle settings.gradle build.sh
The available OpenSearch plugins and OpenSearch Dashboards plugins are listed on the documentation website.
If you create a new plugin or update the name of an existing one, make sure to update the list of plugins. You can either edit the OpenSearch plugins doc page or OpenSearch Dashboards plugins doc page in the documentation repo, or open a documentation issue.