elasticsearch/server/build.gradle
Jack Conradson f7a7f0b923
Generate a test dependencies file to support unit tests in entitlements (#127486)
Generates a test file with the following information and format:

{
    "component": "<component name>",
    "locations": [
        {
            "representative_class": <class name with package>,
            "module": "<module name>"
        },
        ...
    ]
}

For painless:

{
    "component": "lang-painless",
    "locations": [
        {
            "representative_class": "org/objectweb/asm/tree/analysis/Analyzer.class",
            "module": "org.objectweb.asm.tree.analysis"
        },
        ...
    ]
}

Then it copies the following files into the jar for consumption by unit tests:

* META-INF/plugin-test-build-info.json
* META-INF/es-plugins/<plugin name>/plugin-descriptor.properties
* META-INF/es-plugins/<plugin name>/entitlement-policy.yaml

For server, the files in the jar become the following:

* META-INF/server-test-build-info.json

This should provide enough information for BootstrapForTesting to be 
able to build a mapping of caller class to policy file using the class file 
to look up the jar or directory within the class path and then associating 
that with it's specified module and finally using the specified module to 
look up the appropriate entitlement policy. 

caller class -> specified module -> entitlement policy


---------

Co-authored-by: Patrick Doyle <patrick.doyle@elastic.co>
2025-05-21 16:21:28 -07:00

293 lines
12 KiB
Groovy

/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
apply plugin: 'elasticsearch.build'
apply plugin: 'elasticsearch.publish'
apply plugin: 'elasticsearch.internal-cluster-test'
apply plugin: 'elasticsearch.internal-test-artifact'
apply plugin: 'elasticsearch.test-build-info'
publishing {
publications {
elastic {
artifactId = 'elasticsearch'
}
}
}
base {
archivesName = 'elasticsearch'
}
dependencies {
api project(':libs:core')
api project(':libs:logging')
api project(':libs:x-content')
api project(":libs:geo")
api project(":libs:lz4")
api project(":libs:plugin-api")
api project(":libs:plugin-analysis-api")
api project(':libs:grok')
api project(":libs:tdigest")
implementation project(":libs:simdvec")
implementation project(":libs:entitlement")
// lucene
api "org.apache.lucene:lucene-core:${versions.lucene}"
api "org.apache.lucene:lucene-analysis-common:${versions.lucene}"
api "org.apache.lucene:lucene-backward-codecs:${versions.lucene}"
api "org.apache.lucene:lucene-facet:${versions.lucene}"
api "org.apache.lucene:lucene-grouping:${versions.lucene}"
api "org.apache.lucene:lucene-highlighter:${versions.lucene}"
api "org.apache.lucene:lucene-join:${versions.lucene}"
api "org.apache.lucene:lucene-memory:${versions.lucene}"
api "org.apache.lucene:lucene-misc:${versions.lucene}"
api "org.apache.lucene:lucene-queries:${versions.lucene}"
api "org.apache.lucene:lucene-queryparser:${versions.lucene}"
api "org.apache.lucene:lucene-sandbox:${versions.lucene}"
api "org.apache.lucene:lucene-suggest:${versions.lucene}"
// utilities
api project(":libs:cli")
implementation 'com.carrotsearch:hppc:0.8.1'
// precentil ranks aggregation
api 'org.hdrhistogram:HdrHistogram:2.1.9'
// logging
api "org.apache.logging.log4j:log4j-api:${versions.log4j}"
api "org.apache.logging.log4j:log4j-core:${versions.log4j}"
// access to native functions
implementation project(':libs:native')
api "co.elastic.logging:log4j2-ecs-layout:${versions.ecsLogging}"
api "co.elastic.logging:ecs-logging-core:${versions.ecsLogging}"
testImplementation(project(":test:framework")) {
// tests use the locally compiled version of server
exclude group: 'org.elasticsearch', module: 'server'
}
internalClusterTestImplementation(project(":test:framework")) {
exclude group: 'org.elasticsearch', module: 'server'
}
internalClusterTestImplementation(project(':modules:reindex'))
internalClusterTestImplementation(project(':modules:mapper-extras'))
internalClusterTestImplementation(project(':modules:data-streams'))
}
spotless {
java {
targetExclude "src/main/java/org/elasticsearch/index/IndexVersion.java"
}
}
tasks.named("forbiddenPatterns").configure {
exclude '**/*.json'
exclude '**/*.jmx'
exclude '**/*.dic'
exclude '**/*.binary'
exclude '**/*.st'
}
tasks.named('internalClusterTestTestingConventions').configure {
baseClass "org.elasticsearch.test.AbstractMultiClustersTestCase"
baseClass "org.elasticsearch.test.ESIntegTestCase"
baseClass "org.elasticsearch.test.ESSingleNodeTestCase"
}
File generatedResourcesDir = new File(buildDir, 'generated-resources')
def generateModulesList = tasks.register("generateModulesList") {
List<String> modules = project(':modules').subprojects.collect { it.name }
modules.add('x-pack')
File modulesFile = new File(generatedResourcesDir, "modules.txt")
inputs.property('modules', modules)
outputs.file(modulesFile)
doLast {
modulesFile.parentFile.mkdirs()
modulesFile.setText(modules.join('\n'), 'UTF-8')
}
}
def generatePluginsList = tasks.register("generatePluginsList") {
Set<String> plugins = new TreeSet<>(project(':plugins').childProjects.keySet())
plugins.remove('example')
File pluginsFile = new File(generatedResourcesDir, 'plugins.txt')
inputs.property('plugins', plugins)
outputs.file(pluginsFile)
doLast {
pluginsFile.parentFile.mkdirs()
pluginsFile.setText(plugins.join('\n'), 'UTF-8')
}
}
sourceSets.main.output.dir(generatedResourcesDir)
sourceSets.main.compiledBy(generateModulesList, generatePluginsList)
if (buildParams.snapshotBuild == false) {
tasks.named("test").configure {
systemProperty 'es.index_mode_feature_flag_registered', 'true'
}
tasks.named("internalClusterTest").configure {
systemProperty 'es.index_mode_feature_flag_registered', 'true'
}
}
tasks.named("test").configure {
systemProperty 'es.insecure_network_trace_enabled', 'true'
filter {
excludeTestsMatching("*.TransportServiceHandshakeTests.testAcceptsMismatchedServerlessBuildHash")
}
excludes << '**/IndexSettingsOverrideTests.class'
}
// There are tests rely on system properties to be configured differently. They must run in a separate test job
// since the default does not work for them and configuring the system properties inside the test class/method
// is too late because fields based on the system properties are often initialized statically.
TaskProvider<Test> systemPropertiesOverrideTest = tasks.register("systemPropertiesOverrideTest", Test) {
include '**/IndexSettingsOverrideTests.class'
include '**/TransportServiceHandshakeTests.class'
filter {
includeTestsMatching("*.TransportServiceHandshakeTests.testAcceptsMismatchedServerlessBuildHash")
includeTestsMatching("*.IndexSettingsOverrideTests.*")
}
systemProperty 'es.stateless.allow.index.refresh_interval.override', 'true'
systemProperty 'es.serverless_transport', 'true'
classpath = sourceSets.test.runtimeClasspath
testClassesDirs = sourceSets.test.output.classesDirs
}
tasks.named("check").configure {
dependsOn(systemPropertiesOverrideTest)
}
tasks.named("thirdPartyAudit").configure {
ignoreMissingClasses(
// from com.fasterxml.jackson.dataformat.yaml.YAMLMapper (jackson-dataformat-yaml)
'com.fasterxml.jackson.databind.ObjectMapper',
// from log4j
'com.conversantmedia.util.concurrent.SpinPolicy',
'com.fasterxml.jackson.core.JsonGenerator',
'com.fasterxml.jackson.core.JsonParser',
'com.fasterxml.jackson.core.JsonParser$Feature',
'com.fasterxml.jackson.core.JsonToken',
'com.fasterxml.jackson.core.PrettyPrinter',
'com.fasterxml.jackson.core.type.TypeReference',
'com.fasterxml.jackson.dataformat.yaml.YAMLMapper',
'com.fasterxml.jackson.databind.SerializationFeature',
'com.fasterxml.jackson.annotation.JsonInclude$Include',
'com.fasterxml.jackson.databind.DeserializationContext',
'com.fasterxml.jackson.databind.DeserializationFeature',
'com.fasterxml.jackson.databind.JsonMappingException',
'com.fasterxml.jackson.databind.JsonNode',
'com.fasterxml.jackson.databind.Module$SetupContext',
'com.fasterxml.jackson.databind.ObjectReader',
'com.fasterxml.jackson.databind.ObjectWriter',
'com.fasterxml.jackson.databind.SerializerProvider',
'com.fasterxml.jackson.databind.deser.std.StdDeserializer',
'com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer',
'com.fasterxml.jackson.databind.module.SimpleModule',
'com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter',
'com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider',
'com.fasterxml.jackson.databind.ser.std.StdScalarSerializer',
'com.fasterxml.jackson.databind.ser.std.StdSerializer',
'com.fasterxml.jackson.dataformat.xml.JacksonXmlModule',
'com.fasterxml.jackson.dataformat.xml.XmlMapper',
'com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter',
'org.fusesource.jansi.Ansi',
'org.fusesource.jansi.AnsiRenderer$Code',
'com.lmax.disruptor.EventFactory',
'com.lmax.disruptor.EventTranslator',
'com.lmax.disruptor.EventTranslatorTwoArg',
'com.lmax.disruptor.EventTranslatorVararg',
'com.lmax.disruptor.ExceptionHandler',
'com.lmax.disruptor.LifecycleAware',
'com.lmax.disruptor.RingBuffer',
'com.lmax.disruptor.Sequence',
'com.lmax.disruptor.SequenceBarrier',
'com.lmax.disruptor.SequenceReportingEventHandler',
'com.lmax.disruptor.TimeoutException',
'com.lmax.disruptor.WaitStrategy',
'com.lmax.disruptor.dsl.Disruptor',
'com.lmax.disruptor.dsl.ProducerType',
'javax.jms.Connection',
'javax.jms.ConnectionFactory',
'javax.jms.Destination',
'javax.jms.JMSException',
'javax.jms.MapMessage',
'javax.jms.Message',
'javax.jms.MessageConsumer',
'javax.jms.MessageProducer',
'javax.jms.Session',
'javax.mail.Authenticator',
'javax.mail.Message$RecipientType',
'javax.mail.PasswordAuthentication',
'javax.mail.Session',
'javax.mail.Transport',
'javax.mail.internet.InternetAddress',
'javax.mail.internet.InternetHeaders',
'javax.mail.internet.MimeMessage',
'javax.mail.internet.MimeMultipart',
'javax.mail.internet.MimeUtility',
'org.apache.commons.compress.compressors.CompressorStreamFactory',
'org.apache.commons.compress.utils.IOUtils',
'org.apache.commons.csv.CSVFormat',
'org.apache.commons.csv.QuoteMode',
'org.apache.kafka.clients.producer.Producer',
'org.apache.kafka.clients.producer.RecordMetadata',
'org.codehaus.stax2.XMLStreamWriter2',
'org.jctools.queues.MpscArrayQueue',
'org.osgi.framework.Bundle',
'org.osgi.framework.BundleActivator',
'org.osgi.framework.BundleContext',
'org.osgi.framework.BundleEvent',
'org.osgi.framework.BundleReference',
'org.osgi.framework.FrameworkUtil',
'org.osgi.framework.ServiceReference',
'org.osgi.framework.ServiceRegistration',
'org.osgi.framework.SynchronousBundleListener',
'org.osgi.framework.wiring.BundleWire',
'org.osgi.framework.wiring.BundleWiring',
'org.zeromq.ZMQ$Context',
'org.zeromq.ZMQ$Socket',
'org.zeromq.ZMQ',
)
ignoreMissingClasses 'javax.xml.bind.DatatypeConverter'
}
tasks.named("dependencyLicenses").configure {
mapping from: /lucene-.*/, to: 'lucene'
mapping from: /log4j-.*/, to: 'log4j'
configureDependencies(
project.configurations.runtimeClasspath, project.configurations.resolveableCompileOnly, identifier -> {
return identifier instanceof ModuleComponentIdentifier
(identifier.moduleIdentifier.name == 'jna' || identifier.moduleIdentifier.name == 'securesm')
})
}
tasks.named("licenseHeaders").configure {
// Ignore our vendored version of Google Guice
excludes << 'org/elasticsearch/injection/guice/**/*'
// Ignore temporary copies of impending 8.7 Lucene classes
excludes << 'org/apache/lucene/search/RegExp87*'
excludes << 'org/apache/lucene/search/RegexpQuery87*'
}
tasks.withType(Checkstyle.class).configureEach { t -> t.getMaxHeapSize().set("2g") }
tasks.named("generateTestBuildInfo").configure {
t -> {
t.getComponentName().set("server")
t.getOutputFile().set(project.getLayout().getBuildDirectory().file("generated-build-info/server-test-build-info.json"))
}
}