/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. * * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ import java.util.concurrent.Callable import org.opensearch.gradle.test.RestIntegTestTask import org.opensearch.gradle.testclusters.StandaloneRestIntegTestTask buildscript { ext { opensearch_group = "org.opensearch" isSnapshot = "true" == System.getProperty("build.snapshot", "true") opensearch_version = System.getProperty("opensearch.version", "3.0.0-SNAPSHOT") buildVersionQualifier = System.getProperty("build.version_qualifier", "") // 3.0.0-SNAPSHOT -> 3.0.0.0-SNAPSHOT version_tokens = opensearch_version.tokenize('-') opensearch_build = version_tokens[0] + '.0' plugin_no_snapshot = opensearch_build if (buildVersionQualifier) { opensearch_build += "-${buildVersionQualifier}" plugin_no_snapshot += "-${buildVersionQualifier}" } if (isSnapshot) { opensearch_build += "-SNAPSHOT" } opensearch_no_snapshot = opensearch_version.replace("-SNAPSHOT","") js_resource_folder = "src/test/resources/job-scheduler" common_utils_version = System.getProperty("common_utils.version", opensearch_build) job_scheduler_version = System.getProperty("job_scheduler.version", opensearch_build) bwcVersionShort = "2.10.0" bwcVersion = bwcVersionShort + ".0" bwcOpenSearchADDownload = 'https://ci.opensearch.org/ci/dbc/distribution-build-opensearch/' + bwcVersionShort + '/latest/linux/x64/tar/builds/' + 'opensearch/plugins/opensearch-anomaly-detection-' + bwcVersion + '.zip' bwcOpenSearchJSDownload = 'https://ci.opensearch.org/ci/dbc/distribution-build-opensearch/' + bwcVersionShort + '/latest/linux/x64/tar/builds/' + 'opensearch/plugins/opensearch-job-scheduler-' + bwcVersion + '.zip' baseName = "adBwcCluster" bwcFilePath = "src/test/resources/org/opensearch/ad/bwc/" bwcJobSchedulerPath = bwcFilePath + "job-scheduler/" bwcAnomalyDetectionPath = bwcFilePath + "anomaly-detection/" // gradle build won't print logs during test by default unless there is a failure. // It is useful to record intermediately information like prediction precision and recall. // This option turn on log printing during tests. printLogs = "true" == System.getProperty("test.logs", "false") } repositories { mavenLocal() maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "${opensearch_group}.gradle:build-tools:${opensearch_version}" } } plugins { id 'nebula.ospackage' version "8.3.0" apply false id "com.diffplug.gradle.spotless" version "3.26.1" id 'java-library' // Gradle 7.6 support was added in test-retry 1.4.0. id 'org.gradle.test-retry' version '1.4.1' } tasks.withType(JavaCompile) { options.encoding = "UTF-8" } tasks.withType(Test) { systemProperty "file.encoding", "UTF-8" jvmArgs("--add-opens", "java.base/java.time=ALL-UNNAMED") jvmArgs("--add-opens", "java.base/java.util.stream=ALL-UNNAMED") // PowerMock related tests like SearchFeatureDaoTests relies on modifying the bytecode of // classes during runtime, which can conflict with the module system introduced in Java 9. // To resolve this issue, we use the --add-opens option to explicitly open the java.util // and java.lang package to PowerMock. This option allows PowerMock to access non-public // members of the java.util and java.lang package. jvmArgs('--add-opens', 'java.base/java.util=ALL-UNNAMED') jvmArgs('--add-opens', 'java.base/java.lang=ALL-UNNAMED') } tasks.withType(Javadoc) { options.encoding = 'UTF-8' } tasks.withType(AbstractArchiveTask).configureEach { preserveFileTimestamps = false reproducibleFileOrder = true } repositories { mavenLocal() maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } mavenCentral() maven { url "https://plugins.gradle.org/m2/" } maven { url "https://d1nvenhzbhpy0q.cloudfront.net/snapshots/lucene/" } } configurations { zipArchive //hamcrest-core needs to be ignored since it causes jar hell exception due to a conflict during testing testImplementation { exclude group: 'org.hamcrest', module: 'hamcrest-core' } } dependencies { zipArchive group: 'org.opensearch.plugin', name:'opensearch-job-scheduler', version: "${opensearch_build}" implementation "org.opensearch:opensearch:${opensearch_version}" compileOnly "org.opensearch.plugin:opensearch-scripting-painless-spi:${opensearch_version}" compileOnly "org.opensearch:opensearch-job-scheduler-spi:${job_scheduler_version}" implementation "org.opensearch:common-utils:${common_utils_version}" implementation "org.opensearch.client:opensearch-rest-client:${opensearch_version}" compileOnly group: 'com.google.guava', name: 'guava', version:'32.0.1-jre' compileOnly group: 'com.google.guava', name: 'failureaccess', version:'1.0.1' implementation group: 'org.javassist', name: 'javassist', version:'3.28.0-GA' implementation group: 'org.apache.commons', name: 'commons-math3', version: '3.6.1' implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.9' implementation group: 'com.yahoo.datasketches', name: 'sketches-core', version: '0.13.4' implementation group: 'com.yahoo.datasketches', name: 'memory', version: '0.12.2' implementation group: 'commons-lang', name: 'commons-lang', version: '2.6' implementation group: 'org.apache.commons', name: 'commons-pool2', version: '2.10.0' implementation 'software.amazon.randomcutforest:randomcutforest-serialization:3.0-rc3' implementation 'software.amazon.randomcutforest:randomcutforest-parkservices:3.0-rc3' implementation 'software.amazon.randomcutforest:randomcutforest-core:3.0-rc3' // we inherit jackson-core from opensearch core implementation "com.fasterxml.jackson.core:jackson-databind:2.14.1" implementation "com.fasterxml.jackson.core:jackson-annotations:2.14.1" // used for serializing/deserializing rcf models. implementation group: 'io.protostuff', name: 'protostuff-core', version: '1.8.0' implementation group: 'io.protostuff', name: 'protostuff-runtime', version: '1.8.0' implementation group: 'io.protostuff', name: 'protostuff-api', version: '1.8.0' implementation group: 'io.protostuff', name: 'protostuff-collectionschema', version: '1.8.0' implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0' implementation "org.jacoco:org.jacoco.agent:0.8.5" implementation ("org.jacoco:org.jacoco.ant:0.8.5") { exclude group: 'org.ow2.asm', module: 'asm-commons' exclude group: 'org.ow2.asm', module: 'asm' exclude group: 'org.ow2.asm', module: 'asm-tree' } testImplementation group: 'pl.pragmatists', name: 'JUnitParams', version: '1.1.1' testImplementation group: 'org.mockito', name: 'mockito-core', version: '2.25.0' testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.2' testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.2' testImplementation group: 'org.powermock', name: 'powermock-module-junit4-common', version: '2.0.2' testImplementation group: 'org.powermock', name: 'powermock-core', version: '2.0.2' testImplementation group: 'org.powermock', name: 'powermock-api-support', version: '2.0.2' testImplementation group: 'org.powermock', name: 'powermock-reflect', version: '2.0.2' testImplementation group: 'org.objenesis', name: 'objenesis', version: '3.0.1' testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.9.15' testImplementation group: 'net.bytebuddy', name: 'byte-buddy-agent', version: '1.9.15' testCompileOnly 'org.apiguardian:apiguardian-api:1.1.0' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.2' testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2' testImplementation "org.opensearch:opensearch-core:${opensearch_version}" testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.7.2' testCompileOnly 'junit:junit:4.13.2' } apply plugin: 'java' apply plugin: 'idea' apply plugin: 'opensearch.opensearchplugin' apply plugin: 'opensearch.testclusters' apply plugin: 'base' apply plugin: 'jacoco' apply plugin: 'eclipse' apply plugin: 'opensearch.pluginzip' ext { isSnapshot = "true" == System.getProperty("build.snapshot", "true") buildVersionQualifier = System.getProperty("build.version_qualifier") } allprojects { group = 'org.opensearch' version = "${opensearch_build}" plugins.withId('java') { sourceCompatibility = targetCompatibility = JavaVersion.VERSION_11 } } ext { projectSubstitutions = [:] licenseFile = rootProject.file('LICENSE.txt') noticeFile = rootProject.file('NOTICE.txt') } opensearchplugin { name 'opensearch-time-series-analytics' description 'OpenSearch time series analytics plugin' classname 'org.opensearch.timeseries.TimeSeriesAnalyticsPlugin' extendedPlugins = ['lang-painless', 'opensearch-job-scheduler'] } // Handle case where older versions of esplugin doesn't expose the joda time version it uses configurations.all { if (it.state != Configuration.State.UNRESOLVED) return resolutionStrategy { force "joda-time:joda-time:${versions.joda}" force "commons-logging:commons-logging:${versions.commonslogging}" force "org.apache.httpcomponents.core5:httpcore5:${versions.httpcore5}" force "org.apache.httpcomponents.client5:httpclient5:${versions.httpclient5}" force "commons-codec:commons-codec:${versions.commonscodec}" force "org.mockito:mockito-core:2.25.0" force "org.objenesis:objenesis:3.0.1" force "net.bytebuddy:byte-buddy:1.9.15" force "net.bytebuddy:byte-buddy-agent:1.9.15" force "com.google.code.gson:gson:2.8.9" force "junit:junit:4.13.2" } } publishing { publications { pluginZip(MavenPublication) { publication -> pom { name = opensearchplugin.name description = opensearchplugin.description groupId = "org.opensearch.plugin" 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/anomaly-detection" } } } } } repositories { maven { name = "Snapshots" url = "https://aws.oss.sonatype.org/content/repositories/snapshots" credentials { username "$System.env.SONATYPE_USERNAME" password "$System.env.SONATYPE_PASSWORD" } } } } tasks.named('forbiddenApisMain').configure { // Only enable limited check because AD code has too many violations. replaceSignatureFiles 'jdk-signatures' signaturesFiles += files('src/forbidden/ad-signatures.txt') } //Adds custom file that only has some of the checks for testApis checks since too many violations //For example, we have to allow @Test to be used in test classes not inherited from LuceneTestCase. //example: warning for every file: `Forbidden annotation use: org.junit.Test [defaultMessage Just name your test method testFooBar]` forbiddenApisTest.setSignaturesFiles(files('src/forbidden/ad-test-signatures.txt')) // Allow test cases to be named Tests without having to be inherited from LuceneTestCase. // see https://github.com/elastic/elasticsearch/blob/323f312bbc829a63056a79ebe45adced5099f6e6/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java testingConventions.enabled = false licenseHeaders.enabled = true dependencyLicenses.enabled = false thirdPartyAudit.enabled = false loggerUsageCheck.enabled = false // See package README.md for details on using these tasks. def _numNodes = findProperty('numNodes') as Integer ?: 1 def opensearch_tmp_dir = rootProject.file('build/private/opensearch_tmp').absoluteFile opensearch_tmp_dir.mkdirs() boolean isCiServer = System.getenv().containsKey("CI") test { retry { if (isCiServer) { failOnPassedAfterRetry = false maxRetries = 6 maxFailures = 10 } } include '**/*Tests.class' systemProperty 'tests.security.manager', 'false' if (System.getProperty("model-benchmark") == null || System.getProperty("model-benchmark") == "false") { filter { excludeTestsMatching "org.opensearch.ad.ml.HCADModelPerfTests" } } } task integTest(type: RestIntegTestTask) { description = "Run tests against a cluster" testClassesDirs = sourceSets.test.output.classesDirs classpath = sourceSets.test.runtimeClasspath } tasks.named("check").configure { dependsOn(integTest) } integTest { retry { if (isCiServer) { failOnPassedAfterRetry = false maxRetries = 6 maxFailures = 10 } } dependsOn "bundlePlugin" systemProperty 'tests.security.manager', 'false' systemProperty 'java.io.tmpdir', opensearch_tmp_dir.absolutePath systemProperty "https", System.getProperty("https") systemProperty "user", System.getProperty("user") systemProperty "password", System.getProperty("password") // Only rest case can run with remote cluster if (System.getProperty("tests.rest.cluster") != null) { filter { includeTestsMatching "org.opensearch.ad.rest.*IT" includeTestsMatching "org.opensearch.ad.e2e.*IT" } } if (System.getProperty("https") == null || System.getProperty("https") == "false") { filter { excludeTestsMatching "org.opensearch.ad.rest.SecureADRestIT" } } if (System.getProperty("tests.rest.bwcsuite") == null) { filter { excludeTestsMatching "org.opensearch.ad.bwc.*IT" } } if (System.getProperty("model-benchmark") == null || System.getProperty("model-benchmark") == "false") { filter { excludeTestsMatching "org.opensearch.ad.e2e.SingleStreamModelPerfIT" } } // The 'doFirst' delays till execution time. doFirst { // Tell the test JVM if the cluster JVM is running under a debugger so that tests can // use longer timeouts for requests. def isDebuggingCluster = getDebug() || System.getProperty("test.debug") != null systemProperty 'cluster.debug', isDebuggingCluster // Set number of nodes system property to be used in tests systemProperty 'cluster.number_of_nodes', "${_numNodes}" // There seems to be an issue when running multi node run or integ tasks with unicast_hosts // not being written, the waitForAllConditions ensures it's written getClusters().forEach { cluster -> cluster.waitForAllConditions() } } // The --debug-jvm command-line option makes the cluster debuggable; this makes the tests debuggable if (System.getProperty("test.debug") != null) { jvmArgs '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005' } if (printLogs) { testLogging { showStandardStreams = true outputs.upToDateWhen {false} } } } testClusters.integTest { testDistribution = "ARCHIVE" // Cluster shrink exception thrown if we try to set numberOfNodes to 1, so only apply if > 1 if (_numNodes > 1) numberOfNodes = _numNodes // When running integration tests it doesn't forward the --debug-jvm to the cluster anymore // i.e. we have to use a custom property to flag when we want to debug elasticsearch JVM // since we also support multi node integration tests we increase debugPort per node if (System.getProperty("opensearch.debug") != null) { def debugPort = 5005 nodes.forEach { node -> node.jvmArgs("-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=*:${debugPort}") debugPort += 1 } } plugin(project.tasks.bundlePlugin.archiveFile) plugin(provider(new Callable(){ @Override RegularFile call() throws Exception { return new RegularFile() { @Override File getAsFile() { return configurations.zipArchive.asFileTree.getSingleFile() } } } })) // As of ES 7.7.0 the opendistro-anomaly-detection plugin is being added to the list of plugins for the testCluster during build before // the opensearch-job-scheduler plugin, which is causing build failures. From the stack trace, this looks like a bug. // // Exception in thread "main" java.lang.IllegalArgumentException: Missing plugin [opensearch-job-scheduler], dependency of [opendistro-anomaly-detection] // at org.opensearch.plugins.PluginsService.addSortedBundle(PluginsService.java:452) // // One explanation is that ES build script sort plugins according to the natural ordering of their names. // opendistro-anomaly-detection comes before opensearch-job-scheduler. // // The following is a comparison of different plugin installation order: // Before 7.7: // ./bin/elasticsearch-plugin install --batch file:opendistro-anomaly-detection.zip file:opensearch-job-scheduler.zip // // After 7.7: // ./bin/elasticsearch-plugin install --batch file:opensearch-job-scheduler.zip file:opendistro-anomaly-detection.zip // // A temporary hack is to reorder the plugins list after evaluation but prior to task execution when the plugins are installed. nodes.each { node -> def plugins = node.plugins def firstPlugin = plugins.get(0) plugins.remove(0) plugins.add(firstPlugin) } } task integTestRemote(type: RestIntegTestTask) { testClassesDirs = sourceSets.test.output.classesDirs classpath = sourceSets.test.runtimeClasspath systemProperty 'tests.security.manager', 'false' systemProperty 'java.io.tmpdir', opensearch_tmp_dir.absolutePath systemProperty "https", System.getProperty("https") systemProperty "user", System.getProperty("user") systemProperty "password", System.getProperty("password") // Only rest case can run with remote cluster if (System.getProperty("tests.rest.cluster") != null) { filter { includeTestsMatching "org.opensearch.ad.rest.*IT" includeTestsMatching "org.opensearch.ad.e2e.*IT" } } if (System.getProperty("https") == null || System.getProperty("https") == "false") { filter { excludeTestsMatching "org.opensearch.ad.rest.SecureADRestIT" } } } 2.times {i -> testClusters { "${baseName}$i" { testDistribution = "ARCHIVE" versions = [bwcVersionShort, opensearch_version] numberOfNodes = 3 plugin(provider(new Callable(){ @Override RegularFile call() throws Exception { return new RegularFile() { @Override File getAsFile() { if (new File("$project.rootDir/$bwcFilePath/job-scheduler/$bwcVersion").exists()) { project.delete(files("$project.rootDir/$bwcFilePath/job-scheduler/$bwcVersion")) } project.mkdir bwcJobSchedulerPath + bwcVersion ant.get(src: bwcOpenSearchJSDownload, dest: bwcJobSchedulerPath + bwcVersion, httpusecaches: false) return fileTree(bwcJobSchedulerPath + bwcVersion).getSingleFile() } } } })) plugin(provider(new Callable(){ @Override RegularFile call() throws Exception { return new RegularFile() { @Override File getAsFile() { if (new File("$project.rootDir/$bwcFilePath/anomaly-detection/$bwcVersion").exists()) { project.delete(files("$project.rootDir/$bwcFilePath/anomaly-detection/$bwcVersion")) } project.mkdir bwcAnomalyDetectionPath + bwcVersion ant.get(src: bwcOpenSearchADDownload, dest: bwcAnomalyDetectionPath + bwcVersion, httpusecaches: false) return fileTree(bwcAnomalyDetectionPath + bwcVersion).getSingleFile() } } } })) setting 'path.repo', "${buildDir}/cluster/shared/repo/${baseName}" setting 'http.content_type.required', 'true' } } } List> plugins = [ provider(new Callable(){ @Override RegularFile call() throws Exception { return new RegularFile() { @Override File getAsFile() { return configurations.zipArchive.asFileTree.getSingleFile() } } } }), provider(new Callable(){ @Override RegularFile call() throws Exception { return new RegularFile() { @Override File getAsFile() { return fileTree(bwcFilePath + "anomaly-detection/" + project.version).getSingleFile() } } } }) ] // Creates 2 test clusters with 3 nodes of the old version. 2.times {i -> task "${baseName}#oldVersionClusterTask$i"(type: StandaloneRestIntegTestTask) { useCluster testClusters."${baseName}$i" filter { includeTestsMatching "org.opensearch.ad.bwc.*IT" } systemProperty 'tests.rest.bwcsuite', 'old_cluster' systemProperty 'tests.rest.bwcsuite_round', 'old' systemProperty 'tests.plugin_bwc_version', bwcVersion nonInputProperties.systemProperty('tests.rest.cluster', "${-> testClusters."${baseName}$i".allHttpSocketURI.join(",")}") nonInputProperties.systemProperty('tests.clustername', "${-> testClusters."${baseName}$i".getName()}") } } // Upgrades one node of the old cluster to new OpenSearch version with upgraded plugin version // This results in a mixed cluster with 2 nodes on the old version and 1 upgraded node. // This is also used as a one third upgraded cluster for a rolling upgrade. task "${baseName}#mixedClusterTask"(type: StandaloneRestIntegTestTask) { useCluster testClusters."${baseName}0" dependsOn "${baseName}#oldVersionClusterTask0" doFirst { testClusters."${baseName}0".upgradeNodeAndPluginToNextVersion(plugins) } filter { includeTestsMatching "org.opensearch.ad.bwc.*IT" } systemProperty 'tests.rest.bwcsuite', 'mixed_cluster' systemProperty 'tests.rest.bwcsuite_round', 'first' systemProperty 'tests.plugin_bwc_version', bwcVersion nonInputProperties.systemProperty('tests.rest.cluster', "${-> testClusters."${baseName}0".allHttpSocketURI.join(",")}") nonInputProperties.systemProperty('tests.clustername', "${-> testClusters."${baseName}0".getName()}") } // Upgrades the second node to new OpenSearch version with upgraded plugin version after the first node is upgraded. // This results in a mixed cluster with 1 node on the old version and 2 upgraded nodes. // This is used for rolling upgrade. task "${baseName}#twoThirdsUpgradedClusterTask"(type: StandaloneRestIntegTestTask) { dependsOn "${baseName}#mixedClusterTask" useCluster testClusters."${baseName}0" doFirst { testClusters."${baseName}0".upgradeNodeAndPluginToNextVersion(plugins) } filter { includeTestsMatching "org.opensearch.ad.bwc.*IT" } systemProperty 'tests.rest.bwcsuite', 'mixed_cluster' systemProperty 'tests.rest.bwcsuite_round', 'second' systemProperty 'tests.plugin_bwc_version', bwcVersion nonInputProperties.systemProperty('tests.rest.cluster', "${-> testClusters."${baseName}0".allHttpSocketURI.join(",")}") nonInputProperties.systemProperty('tests.clustername', "${-> testClusters."${baseName}0".getName()}") } // Upgrades the third node to new OpenSearch version with upgraded plugin version after the second node is upgraded. // This results in a fully upgraded cluster. // This is used for rolling upgrade. task "${baseName}#rollingUpgradeClusterTask"(type: StandaloneRestIntegTestTask) { dependsOn "${baseName}#twoThirdsUpgradedClusterTask" useCluster testClusters."${baseName}0" doFirst { testClusters."${baseName}0".upgradeNodeAndPluginToNextVersion(plugins) } filter { includeTestsMatching "org.opensearch.ad.bwc.*IT" } mustRunAfter "${baseName}#mixedClusterTask" systemProperty 'tests.rest.bwcsuite', 'mixed_cluster' systemProperty 'tests.rest.bwcsuite_round', 'third' systemProperty 'tests.plugin_bwc_version', bwcVersion nonInputProperties.systemProperty('tests.rest.cluster', "${-> testClusters."${baseName}0".allHttpSocketURI.join(",")}") nonInputProperties.systemProperty('tests.clustername', "${-> testClusters."${baseName}0".getName()}") } // Upgrades all the nodes of the old cluster to new OpenSearch version with upgraded plugin version // at the same time resulting in a fully upgraded cluster. task "${baseName}#fullRestartClusterTask"(type: StandaloneRestIntegTestTask) { dependsOn "${baseName}#oldVersionClusterTask1" useCluster testClusters."${baseName}1" doFirst { testClusters."${baseName}1".upgradeAllNodesAndPluginsToNextVersion(plugins) } filter { includeTestsMatching "org.opensearch.ad.bwc.*IT" } systemProperty 'tests.rest.bwcsuite', 'upgraded_cluster' systemProperty 'tests.plugin_bwc_version', bwcVersion nonInputProperties.systemProperty('tests.rest.cluster', "${-> testClusters."${baseName}1".allHttpSocketURI.join(",")}") nonInputProperties.systemProperty('tests.clustername', "${-> testClusters."${baseName}1".getName()}") } // A bwc test suite which runs all the bwc tasks combined. task bwcTestSuite(type: StandaloneRestIntegTestTask) { exclude '**/*Test*' exclude '**/*IT*' dependsOn tasks.named("${baseName}#mixedClusterTask") dependsOn tasks.named("${baseName}#rollingUpgradeClusterTask") dependsOn tasks.named("${baseName}#fullRestartClusterTask") } run { doFirst { // There seems to be an issue when running multi node run or integ tasks with unicast_hosts // not being written, the waitForAllConditions ensures it's written getClusters().forEach { cluster -> cluster.waitForAllConditions() } } useCluster testClusters.integTest } evaluationDependsOnChildren() task release(type: Copy, group: 'build') { dependsOn allprojects*.tasks.build from(zipTree(project.tasks.bundlePlugin.outputs.files.getSingleFile())) into "build/plugins/opensearch-anomaly-detection" includeEmptyDirs = false // ES versions < 6.3 have a top-level opensearch directory inside the plugin zip which we need to remove eachFile { it.path = it.path - "opensearch/" } } List jacocoExclusions = [ // code for configuration, settings, etc is excluded from coverage 'org.opensearch.timeseries.TimeSeriesAnalyticsPlugin', // rest layer is tested in integration testing mostly, difficult to mock all of it 'org.opensearch.ad.rest.*', 'org.opensearch.ad.model.ModelProfileOnNode', 'org.opensearch.ad.model.InitProgressProfile', 'org.opensearch.ad.rest.*', 'org.opensearch.ad.AnomalyDetectorJobRunner', // Class containing just constants. Don't need to test 'org.opensearch.ad.constant.*', 'org.opensearch.forecast.constant.*', 'org.opensearch.timeseries.constant.*', 'org.opensearch.timeseries.settings.TimeSeriesSettings', 'org.opensearch.forecast.settings.ForecastSettings', 'org.opensearch.ad.transport.CronRequest', 'org.opensearch.ad.AnomalyDetectorRunner', // related to transport actions added for security 'org.opensearch.ad.transport.DeleteAnomalyDetectorTransportAction.1', // TODO: unified flow caused coverage drop 'org.opensearch.ad.transport.DeleteAnomalyResultsTransportAction', // TODO: fix unstable code coverage caused by null NodeClient issue // https://github.com/opensearch-project/anomaly-detection/issues/241 'org.opensearch.ad.task.ADBatchTaskRunner', 'org.opensearch.ad.task.ADTaskManager', ] jacocoTestCoverageVerification { violationRules { rule { element = 'CLASS' excludes = jacocoExclusions limit { counter = 'BRANCH' minimum = 0.60 } } rule { element = 'CLASS' excludes = jacocoExclusions limit { counter = 'LINE' value = 'COVEREDRATIO' minimum = 0.75 } } } } jacocoTestReport { reports { xml.enabled = true html.enabled = true } } check.dependsOn jacocoTestCoverageVerification jacocoTestCoverageVerification.dependsOn jacocoTestReport compileJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" test { useJUnitPlatform() } apply plugin: 'nebula.ospackage' // This is afterEvaluate because the bundlePlugin ZIP task is updated afterEvaluate and changes the ZIP name to match the plugin name afterEvaluate { ospackage { packageName = "${name}" release = isSnapshot ? "0.1" : '1' version = "${project.version}" - "-SNAPSHOT" into '/usr/share/opensearch/plugins' from(zipTree(bundlePlugin.archivePath)) { into opensearchplugin.name } user 'root' permissionGroup 'root' fileMode 0644 dirMode 0755 requires('opensearch', versions.opensearch, EQUAL) packager = 'Amazon' vendor = 'Amazon' os = 'LINUX' prefix '/usr' license 'ASL-2.0' maintainer 'OpenSearch ' url 'https://opensearch.org/downloads.html' summary ''' Anomaly Detection plugin for OpenSearch. Reference documentation can be found at https://opensearch.org/docs/monitoring-plugins/ad/index/. '''.stripIndent().replace('\n', ' ').trim() } buildRpm { arch = 'NOARCH' dependsOn 'assemble' finalizedBy 'renameRpm' task renameRpm(type: Copy) { from("$buildDir/distributions") into("$buildDir/distributions") include archiveName rename archiveName, "${packageName}-${version}.rpm" doLast { delete file("$buildDir/distributions/$archiveName") } } } buildDeb { arch = 'all' dependsOn 'assemble' finalizedBy 'renameDeb' task renameDeb(type: Copy) { from("$buildDir/distributions") into("$buildDir/distributions") include archiveName rename archiveName, "${packageName}-${version}.deb" doLast { delete file("$buildDir/distributions/$archiveName") } } } task buildPackages(type: GradleBuild) { tasks = ['build', 'buildRpm', 'buildDeb'] } } spotless { java { removeUnusedImports() importOrder 'java', 'javax', 'org', 'com' eclipse().configFile rootProject.file('.eclipseformat.xml') } } // no need to validate pom, as we do not upload to maven/sonatype validateNebulaPom.enabled = false tasks.withType(licenseHeaders.class) { additionalLicense 'AL ', 'Apache', 'Licensed under the Apache License, Version 2.0 (the "License")' } // show test results so that we can record information like precion/recall results of correctness testing. if (printLogs) { test { testLogging { showStandardStreams = true outputs.upToDateWhen {false} } } } // updateVersion: Task to auto increment to the next development iteration task updateVersion { onlyIf { System.getProperty('newVersion') } doLast { ext.newVersion = System.getProperty('newVersion') println "Setting version to ${newVersion}." // String tokenization to support -SNAPSHOT // Include the required files that needs to be updated with new Version ant.replaceregexp(file:'build.gradle', match: '"opensearch.version", "\\d.*"', replace: '"opensearch.version", "' + newVersion.tokenize('-')[0] + '-SNAPSHOT"', flags:'g', byline:true) } }