Add compatibility testing for JDBC driver (#60409)

This commit adds compatibility testing of our JDBC driver against
different Elasticsearch versions. Although we are really testing the
forwards compatibility nature of the JDBC driver we model the testing
the same as we do existing BWC tests, that is, with the current branch
fetching the earlier versions of the artifact that is to be tested. In
this case, that's the JDBC driver itself.

Because the tests include the JDBC driver jar on it's classpath we had
to change the packaging of the driver jar in order to avoid jarhell and
other conflicting dependency issues when using an old JDBC driver with
later branches. For this we simply relocate all driver dependencies in
the shadow jar under a "shadowed" package. This allows the JDBC driver
to use the correct version of Elasticsearch libs classes, while the
tests themselves use their versions. Since this required a change to the
driver jar compatibility testing can only go back as far as that version
which at the time of this commit is 7.8.1.
This commit is contained in:
Mark Vieira 2020-07-29 10:45:11 -07:00 committed by GitHub
parent e73c8eed33
commit 39fa1c4df0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 158 additions and 100 deletions

View File

@ -98,7 +98,7 @@ dependencies {
api 'com.netflix.nebula:gradle-info-plugin:7.1.3'
api 'org.apache.rat:apache-rat:0.11'
api "org.elasticsearch:jna:5.5.0"
api 'com.github.jengelman.gradle.plugins:shadow:5.1.0'
api 'com.github.jengelman.gradle.plugins:shadow:6.0.0'
api 'de.thetaphi:forbiddenapis:3.0'
api 'com.avast.gradle:gradle-docker-compose-plugin:0.12.1'
api 'org.apache.maven:maven-model:3.6.2'

View File

@ -293,6 +293,11 @@ BuildParams.bwcVersions.forPreviousUnreleased { BwcVersions.UnreleasedVersionInf
createBuildBwcTask(projectName, "${baseDir}/${projectName}", projectArtifact)
}
// Create build tasks for the JDBC driver used for compatibility testing
String jdbcProjectDir = 'x-pack/plugin/sql/jdbc'
File jdbcProjectArtifact = file("${checkoutDir}/${jdbcProjectDir}/build/distributions/x-pack-sql-jdbc-${bwcVersion}-SNAPSHOT.jar")
createBuildBwcTask('jdbc', jdbcProjectDir, jdbcProjectArtifact)
createRunBwcGradleTask("resolveAllBwcDependencies") {
args 'resolveAllDependencies'
}

View File

@ -28,4 +28,4 @@ tasks.named("check").configure {
dependsOn(bwcTestSnapshots)
}
test.enabled = false
tasks.findByName("test")?.enabled = false

View File

@ -35,10 +35,19 @@ tasks.named("dependencyLicenses").configure {
}
shadowJar {
relocate 'com.fasterxml', 'org.elasticsearch.fasterxml'
relocate 'com.fasterxml', 'shadow.fasterxml'
relocate('org.elasticsearch', 'shadow.org.elasticsearch') {
// Don't relocate the JDBC driver classes themselves as that's (mostly) public API
exclude 'org.elasticsearch.xpack.sql.jdbc.*'
}
}
thirdPartyAudit.ignoreMissingClasses(
'com.fasterxml.jackson.databind.ObjectMapper',
'com.fasterxml.jackson.databind.cfg.MapperBuilder'
)
tasks.named("test").configure {
// reset the unit test classpath as using the shadow jar won't work due to relocated packages
classpath = sourceSets.test.runtimeClasspath
}

View File

@ -1,61 +1,103 @@
import org.elasticsearch.gradle.BwcVersions.UnreleasedVersionInfo
import org.elasticsearch.gradle.Version
import org.elasticsearch.gradle.VersionProperties
import org.elasticsearch.gradle.info.BuildParams
import org.elasticsearch.gradle.test.RestIntegTestTask
description = 'Integration tests for SQL JDBC driver'
apply plugin: 'elasticsearch.build'
apply plugin: 'elasticsearch.java'
// Avoid circular dependency
group = "org.elasticsearch.x-pack.qa.sql.jdbc"
group = 'org.elasticsearch.x-pack.qa.sql.jdbc'
dependencies {
api project(":test:framework")
api project(':test:framework')
implementation xpackProject('plugin:sql:sql-proto')
// JDBC testing dependencies
api project(path: xpackModule('sql:jdbc'))
// Actual tests will use the shadow jar
compileOnly(project(path: xpackModule('sql:jdbc'))) {
// Since dependencies will be relocated in the shadow jar, don't attempt to compile against them
transitive = false
}
}
/* disable unit tests because these are all integration tests used
* other qa projects. */
// disable unit tests because these are all integration tests used other qa projects
test.enabled = false
tasks.named("dependencyLicenses").configure { it.enabled = false }
dependenciesInfo.enabled = false
// the main files are actually test files, so use the appropriate forbidden api sigs
tasks.named('forbiddenApisMain').configure {
replaceSignatureFiles 'es-all-signatures', 'es-test-signatures'
}
// just a test fixture: we aren't using this jars in releases and H2GIS requires disabling a lot of checks
thirdPartyAudit.enabled = false
subprojects {
if (subprojects.isEmpty()) {
// leaf project
apply plugin: 'elasticsearch.standalone-rest-test'
} else {
apply plugin: 'elasticsearch.build'
if (subprojects.isEmpty()) {
// leaf project
apply plugin: 'elasticsearch.standalone-rest-test'
apply from: "$rootDir/gradle/bwc-test.gradle"
} else {
apply plugin: 'elasticsearch.java'
}
repositories {
maven {
// Repository for downloading BWC compatible JDBC driver releases
url = 'https://artifacts.elastic.co/maven'
}
}
configurations {
jdbcDriver
}
dependencies {
testImplementation(xpackProject('plugin:sql:qa:jdbc'))
// We use the shadowjar for testing since that's the actual artifact we deliver to users
testCompileOnly project(path: xpackModule('sql:jdbc'), configuration: 'shadow')
jdbcDriver project(path: xpackModule('sql:jdbc'), configuration: 'shadow')
}
if (project.name != 'security') {
// The security project just configures its subprojects
apply plugin: 'elasticsearch.testclusters'
apply plugin: 'elasticsearch.rest-test'
testClusters.all {
testDistribution = 'DEFAULT'
setting 'xpack.ml.enabled', 'false'
setting 'xpack.watcher.enabled', 'false'
}
dependencies {
/* Since we're a standalone rest test we actually get transitive
* dependencies but we don't really want them because they cause
* all kinds of trouble with the jar hell checks. So we suppress
* them explicitly for non-es projects. */
testImplementation(xpackProject('plugin:sql:qa:jdbc')) {
transitive = false
integTest {
runner {
classpath += configurations.jdbcDriver
systemProperty 'jdbc.driver.version', VersionProperties.elasticsearch
}
}
// Configure compatibility testing tasks
for (Version bwcVersion : BuildParams.bwcVersions.indexCompatible) {
// Compatibility testing for JDBC driver started with version 7.9.0
if (bwcVersion.onOrAfter(Version.fromString("7.9.0"))) {
String baseName = "v${bwcVersion}"
UnreleasedVersionInfo unreleasedVersion = BuildParams.bwcVersions.unreleasedInfo(bwcVersion)
Configuration driverConfiguration = configurations.create("jdbcDriver${baseName}")
Object driverDependency = null
if (unreleasedVersion) {
// For unreleased snapshot versions, build them from source
driverDependency = files(project(unreleasedVersion.gradleProjectPath).tasks.named('buildBwcJdbc'))
} else {
// For released versions, download it
driverDependency = "org.elasticsearch.plugin:x-pack-sql-jdbc:${bwcVersion}"
}
testImplementation project(":test:framework")
testRuntimeOnly project(path: xpackModule('sql:jdbc'))
}
if (project.name != 'security') {
// The security project just configures its subprojects
apply plugin: 'elasticsearch.testclusters'
apply plugin: 'elasticsearch.rest-test'
testClusters.integTest {
testDistribution = 'DEFAULT'
setting 'xpack.ml.enabled', 'false'
setting 'xpack.watcher.enabled', 'false'
dependencies {
"jdbcDriver${baseName}"(driverDependency)
}
tasks.create(bwcTaskName(bwcVersion), RestIntegTestTask) {
runner {
classpath += driverConfiguration
systemProperty 'jdbc.driver.version', bwcVersion.toString()
}
}
}
}
}
}

View File

@ -1,7 +1,7 @@
description = 'Run SQL JDBC tests against multiple nodes'
testClusters.integTest {
numberOfNodes = 2
setting 'xpack.security.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
testClusters.all {
numberOfNodes = 2
setting 'xpack.security.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
}

View File

@ -1,4 +1,4 @@
testClusters.integTest {
setting 'xpack.security.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
testClusters.all {
setting 'xpack.security.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
}

View File

@ -1,5 +1,7 @@
import org.elasticsearch.gradle.testclusters.RestTestRunnerTask
dependencies {
testImplementation project(':x-pack:plugin:core')
testImplementation project(':x-pack:plugin:core')
}
Project mainProject = project
@ -7,55 +9,53 @@ Project mainProject = project
configurations.create('testArtifacts')
TaskProvider testJar = tasks.register("testJar", Jar) {
appendix 'test'
from sourceSets.test.output
appendix 'test'
from sourceSets.test.output
}
artifacts {
testArtifacts testJar
testArtifacts testJar
}
// Tests are pushed down to subprojects and will be checked there.
testingConventions.enabled = false
subprojects {
// Use tests from the root security qa project in subprojects
configurations.create('testArtifacts')
// Use tests from the root security qa project in subprojects
configurations.create('testArtifacts')
dependencies {
testImplementation project(":x-pack:plugin:core")
testArtifacts project(path: mainProject.path, configuration: 'testArtifacts')
}
dependencies {
testImplementation project(":x-pack:plugin:core")
testArtifacts project(path: mainProject.path, configuration: 'testArtifacts')
}
testClusters.integTest {
testDistribution = 'DEFAULT'
// Setup auditing so we can use it in some tests
setting 'xpack.security.audit.enabled', 'true'
setting 'xpack.security.enabled', 'true'
setting 'xpack.license.self_generated.type', 'trial'
// Setup roles used by tests
extraConfigFile 'roles.yml', mainProject.file('roles.yml')
/* Setup the one admin user that we run the tests as.
* Tests use "run as" to get different users. */
user username: "test_admin", password: "x-pack-test-password"
}
testClusters.all {
testDistribution = 'DEFAULT'
// Setup auditing so we can use it in some tests
setting 'xpack.security.audit.enabled', 'true'
setting 'xpack.security.enabled', 'true'
setting 'xpack.license.self_generated.type', 'trial'
// Setup roles used by tests
extraConfigFile 'roles.yml', mainProject.file('roles.yml')
/* Setup the one admin user that we run the tests as.
* Tests use "run as" to get different users. */
user username: "test_admin", password: "x-pack-test-password"
}
File testArtifactsDir = project.file("$buildDir/testArtifacts")
TaskProvider copyTestClasses = tasks.register("copyTestClasses", Copy) {
dependsOn configurations.testArtifacts
from { zipTree(configurations.testArtifacts.singleFile) }
into testArtifactsDir
}
File testArtifactsDir = project.file("$buildDir/testArtifacts")
TaskProvider copyTestClasses = tasks.register("copyTestClasses", Copy) {
dependsOn configurations.testArtifacts
from { zipTree(configurations.testArtifacts.singleFile) }
into testArtifactsDir
}
integTest.runner {
dependsOn copyTestClasses
testClassesDirs += project.files(testArtifactsDir)
classpath += configurations.testArtifacts
nonInputProperties.systemProperty 'tests.audit.logfile',
"${-> testClusters.integTest.singleNode().getAuditLog()}"
nonInputProperties.systemProperty 'tests.audit.yesterday.logfile',
"${-> testClusters.integTest.singleNode().getAuditLog().getParentFile()}/integTest_audit-${new Date().format('yyyy-MM-dd')}.json"
}
testingConventions.enabled = false
tasks.withType(RestTestRunnerTask).configureEach {
dependsOn copyTestClasses
testClassesDirs += project.files(testArtifactsDir)
classpath += configurations.testArtifacts
nonInputProperties.systemProperty 'tests.audit.logfile',
"${-> testClusters.integTest.singleNode().getAuditLog()}"
nonInputProperties.systemProperty 'tests.audit.yesterday.logfile',
"${-> testClusters.integTest.singleNode().getAuditLog().getParentFile()}/integTest_audit-${new Date().format('yyyy-MM-dd')}.json"
}
testingConventions.enabled = false
}

View File

@ -1,6 +1,6 @@
apply plugin: 'elasticsearch.test-with-ssl'
testClusters.integTest {
testClusters.all {
// The setup that we actually want
setting 'xpack.license.self_generated.type', 'trial'
setting 'xpack.security.http.ssl.enabled', 'true'

View File

@ -1,7 +1,9 @@
integTest.runner {
systemProperty 'tests.ssl.enabled', 'false'
import org.elasticsearch.gradle.testclusters.RestTestRunnerTask
tasks.withType(RestTestRunnerTask).configureEach {
systemProperty 'tests.ssl.enabled', 'false'
}
testClusters.integTest {
setting 'xpack.license.self_generated.type', 'trial'
testClusters.all {
setting 'xpack.license.self_generated.type', 'trial'
}

View File

@ -1,4 +1,4 @@
testClusters.integTest {
testClusters.all {
setting 'xpack.security.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
}