Skip to content

Commit 37ac6eb

Browse files
committed
Pattern for testing using standarized JVM config
In a previous iteration jvm options were attempted to be configured at the gradle level. This presented a challeng in rspec loading because webmock was not being loaded correctly with the fips providers. That initial approach was also problematic because it introduced a fork in configuration changes between configuring the JVM via the enviornment variables and files for running logstash in the container vs in the tests. This new apprach attempts to separate aout all of the test setup and building in gradle from a pure "just run the tests" task. The fundamental idea is that we dont want to use FIPS mode for downloading dependencies and building/preparing an environment we only want that configured at the very end. This apprach accomplishes that by teasing out the dependencies that trigger downloads etc in gradel from tasks that will only run the tests. The dockerfile order will call all the gradle tasks for setup, then configure FIPS mode and call the tests that should be run under fips mode.
1 parent e30e728 commit 37ac6eb

File tree

5 files changed

+75
-127
lines changed

5 files changed

+75
-127
lines changed

Dockerfile

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ COPY . .
2727

2828
# Initial build using JKS truststore
2929
# ENV JAVA_OPTS="-Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts -Djavax.net.ssl.trustStoreType=JKS -Djavax.net.ssl.trustStorePassword=changeit"
30-
RUN ./gradlew clean bootstrap assemble installDefaultGems --no-daemon
30+
RUN ./gradlew clean bootstrap assemble installDefaultGems testSetup --no-daemon
3131

32+
# CMD ["sleep", "infinity"]
3233
RUN keytool -importkeystore \
3334
-srckeystore $JAVA_HOME/lib/security/cacerts \
3435
-destkeystore /etc/java/security/cacerts.bcfks \
3536
-srcstoretype jks \
3637
-deststoretype bcfks \
37-
-providerpath /root/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bc-fips/2.0.0/ee9ac432cf08f9a9ebee35d7cf8a45f94959a7ab/bc-fips-2.0.0.jar \
38+
-providerpath /logstash/logstash-core/lib/jars/bc-fips-2.0.0.jar \
3839
-provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
3940
-deststorepass changeit \
4041
-srcstorepass changeit \
@@ -45,31 +46,32 @@ RUN keytool -importkeystore \
4546
-destkeystore /etc/java/security/keystore.bcfks \
4647
-srcstoretype jks \
4748
-deststoretype bcfks \
48-
-providerpath /root/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bc-fips/2.0.0/ee9ac432cf08f9a9ebee35d7cf8a45f94959a7ab/bc-fips-2.0.0.jar \
49+
-providerpath /logstash/logstash-core/lib/jars/bc-fips-2.0.0.jar \
4950
-provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
5051
-deststorepass changeit \
5152
-srcstorepass changeit \
5253
-noprompt
5354

55+
5456
# Uncomment this out and build for interactive terminal sessions in a container
5557
# Currently this dockerfile is just for running tests, but I have been also using it to
5658
# do manual validation. Need to think more about how to separate concerns.
57-
# ENV JAVA_SECURITY_PROPERTIES=/etc/java/security/java.security
58-
# ENV JAVA_OPTS="\
59-
# -Djava.security.debug=ssl,provider \
60-
# -Djava.security.properties=${JAVA_SECURITY_PROPERTIES} \
61-
# -Djavax.net.ssl.keyStore=/etc/java/security/keystore.bcfks \
62-
# -Djavax.net.ssl.keyStoreType=BCFKS \
63-
# -Djavax.net.ssl.keyStoreProvider=BCFIPS \
64-
# -Djavax.net.ssl.keyStorePassword=changeit \
65-
# -Djavax.net.ssl.trustStore=/etc/java/security/cacerts.bcfks \
66-
# -Djavax.net.ssl.trustStoreType=BCFKS \
67-
# -Djavax.net.ssl.trustStoreProvider=BCFIPS \
68-
# -Djavax.net.ssl.trustStorePassword=changeit \
69-
# -Dssl.KeyManagerFactory.algorithm=PKIX \
70-
# -Dssl.TrustManagerFactory.algorithm=PKIX \
71-
# -Dorg.bouncycastle.fips.approved_only=true"
59+
ENV JAVA_SECURITY_PROPERTIES=/etc/java/security/java.security
60+
ENV JAVA_OPTS="\
61+
-Djava.security.debug=ssl,provider \
62+
-Djava.security.properties=${JAVA_SECURITY_PROPERTIES} \
63+
-Djavax.net.ssl.keyStore=/etc/java/security/keystore.bcfks \
64+
-Djavax.net.ssl.keyStoreType=BCFKS \
65+
-Djavax.net.ssl.keyStoreProvider=BCFIPS \
66+
-Djavax.net.ssl.keyStorePassword=changeit \
67+
-Djavax.net.ssl.trustStore=/etc/java/security/cacerts.bcfks \
68+
-Djavax.net.ssl.trustStoreType=BCFKS \
69+
-Djavax.net.ssl.trustStoreProvider=BCFIPS \
70+
-Djavax.net.ssl.trustStorePassword=changeit \
71+
-Dssl.KeyManagerFactory.algorithm=PKIX \
72+
-Dssl.TrustManagerFactory.algorithm=PKIX \
73+
-Dorg.bouncycastle.fips.approved_only=true"
7274

7375
# Run tests with BCFKS truststore
74-
CMD ["./gradlew", "--info", "--stacktrace", "test"]
76+
CMD ["./gradlew","-PskipJRubySetup=true", "--info", "--stacktrace", "javaTestsOnly", "rubyTestsOnly"]
7577

build.gradle

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,18 @@ clean {
295295
delete "${projectDir}/logstash-core/src/main/resources/org/logstash/plugins/plugin_aliases.yml"
296296
}
297297

298-
def assemblyDeps = [downloadAndInstallJRuby, assemble] + subprojects.collect {
299-
it.tasks.findByName("assemble")
298+
def getAssemblyDeps() {
299+
return project.hasProperty('skipJRubySetup') ? [] : [downloadAndInstallJRuby, assemble] + subprojects.collect {
300+
it.tasks.findByName("assemble")
301+
}
300302
}
301303

302304
tasks.register("bootstrap") {
303-
dependsOn assemblyDeps
305+
onlyIf { !project.hasProperty('skipJRubySetup') }
306+
dependsOn getAssemblyDeps()
304307
doLast {
305-
setupJruby(projectDir, buildDir)
306-
}
308+
setupJruby(projectDir, buildDir)
309+
}
307310
}
308311

309312

logstash-core/build.gradle

Lines changed: 45 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,12 @@ buildscript {
2727
}
2828
}
2929

30-
plugins {
31-
id "jacoco"
32-
id "org.sonarqube" version "4.3.0.3225"
33-
}
3430

35-
apply plugin: 'jacoco'
36-
apply plugin: "org.sonarqube"
3731

3832
repositories {
3933
mavenCentral()
4034
}
4135

42-
sonarqube {
43-
properties {
44-
property 'sonar.coverage.jacoco.xmlReportPaths', "${buildDir}/reports/jacoco/test/jacocoTestReport.xml"
45-
}
46-
}
47-
48-
jacoco {
49-
toolVersion = "0.8.9"
50-
}
5136

5237

5338
import org.yaml.snakeyaml.Yaml
@@ -110,26 +95,7 @@ configurations.archives {
11095
extendsFrom configurations.javadoc
11196
}
11297

113-
def setupBCProvider() {
114-
println "Setting up BC provider"
115-
System.setProperty("javax.net.ssl.trustStore", "/etc/java/security/cacerts.bcfks")
116-
System.setProperty("javax.net.ssl.trustStoreType", "BCFKS")
117-
System.setProperty("javax.net.ssl.trustStoreProvider", "BCFIPS")
118-
System.setProperty("javax.net.ssl.trustStorePassword", "changeit")
119-
120-
def provider = Class.forName('org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider').getDeclaredConstructor().newInstance()
121-
java.security.Security.insertProviderAt(provider, 1)
122-
}
123-
12498
tasks.register("javaTests", Test) {
125-
doFirst {
126-
configurations.testRuntimeClasspath.resolvedConfiguration.files.each { file ->
127-
if (file.name.startsWith("bc-")) {
128-
println "Found BC jar: ${file}"
129-
}
130-
}
131-
setupBCProvider()
132-
}
13399
dependsOn ':bootstrap'
134100
exclude '/org/logstash/RSpecTests.class'
135101
exclude '/org/logstash/config/ir/ConfigCompilerTest.class'
@@ -143,31 +109,10 @@ tasks.register("javaTests", Test) {
143109
exclude '/org/logstash/plugins/factory/PluginFactoryExtTest.class'
144110
exclude '/org/logstash/execution/ObservedExecutionTest.class'
145111

146-
jacoco {
147-
enabled = true
148-
destinationFile = layout.buildDirectory.file('jacoco/test.exec').get().asFile
149-
classDumpDir = layout.buildDirectory.dir('jacoco/classpathdumps').get().asFile
150-
}
151112
}
152113

153-
jacocoTestReport {
154-
reports {
155-
xml.required = true
156-
html.required = true
157-
}
158-
}
159-
160-
javaTests.finalizedBy(jacocoTestReport)
161114

162115
tasks.register("rubyTests", Test) {
163-
doFirst {
164-
configurations.testRuntimeClasspath.resolvedConfiguration.files.each { file ->
165-
if (file.name.startsWith("bc-")) {
166-
println "Found BC jar: ${file}"
167-
}
168-
}
169-
setupBCProvider()
170-
}
171116
dependsOn compileTestJava
172117
inputs.files fileTree("${projectDir}/lib")
173118
inputs.files fileTree("${projectDir}/spec")
@@ -223,6 +168,50 @@ task generateVersionInfoResources(type: DefaultTask) {
223168
resourceFile.text = "logstash-core: ${logstashCoreVersion}"
224169
}
225170
}
171+
// Test execution tasks without dependencies
172+
tasks.register("javaTestsOnly", Test) {
173+
setDependsOn([])
174+
exclude '/org/logstash/RSpecTests.class'
175+
exclude '/org/logstash/config/ir/ConfigCompilerTest.class'
176+
exclude '/org/logstash/config/ir/CompiledPipelineTest.class'
177+
exclude '/org/logstash/config/ir/EventConditionTest.class'
178+
exclude '/org/logstash/config/ir/PipelineConfigTest.class'
179+
exclude '/org/logstash/config/ir/compiler/OutputDelegatorTest.class'
180+
exclude '/org/logstash/config/ir/compiler/JavaCodecDelegatorTest.class'
181+
exclude '/org/logstash/plugins/NamespacedMetricImplTest.class'
182+
exclude '/org/logstash/plugins/CounterMetricImplTest.class'
183+
exclude '/org/logstash/plugins/factory/PluginFactoryExtTest.class'
184+
exclude '/org/logstash/execution/ObservedExecutionTest.class'
185+
}
186+
187+
tasks.register("rubyTestsOnly", Test) {
188+
setDependsOn([])
189+
inputs.files fileTree("${projectDir}/lib")
190+
inputs.files fileTree("${projectDir}/spec")
191+
systemProperty 'logstash.root.dir', projectDir.parent
192+
193+
include '/org/logstash/RSpecTests.class'
194+
include '/org/logstash/config/ir/ConfigCompilerTest.class'
195+
include '/org/logstash/config/ir/CompiledPipelineTest.class'
196+
include '/org/logstash/config/ir/EventConditionTest.class'
197+
include '/org/logstash/config/ir/PipelineConfigTest.class'
198+
include '/org/logstash/config/ir/compiler/OutputDelegatorTest.class'
199+
include '/org/logstash/config/ir/compiler/JavaCodecDelegatorTest.class'
200+
include '/org/logstash/plugins/NamespacedMetricImplTest.class'
201+
include '/org/logstash/plugins/CounterMetricImplTest.class'
202+
include '/org/logstash/plugins/factory/PluginFactoryExtTest.class'
203+
include '/org/logstash/execution/ObservedExecutionTest.class'
204+
}
205+
206+
// Setup task combining all prerequisites
207+
tasks.register("testSetup") {
208+
dependsOn ':bootstrap'
209+
dependsOn 'classes'
210+
dependsOn 'testClasses'
211+
dependsOn 'compileTestJava'
212+
dependsOn 'copyRuntimeLibs'
213+
dependsOn 'generateVersionInfoResources'
214+
}
226215
sourceSets {
227216
main { output.dir(generateVersionInfoResources.outputs.files) }
228217
}
@@ -294,4 +283,4 @@ dependencies {
294283
api group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.14'
295284
api group: 'commons-codec', name: 'commons-codec', version: '1.17.0'
296285
api group: 'org.apache.httpcomponents', name: 'httpcore', version: '4.4.16'
297-
}
286+
}

rubyUtils.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ def customJRubyVersion = customJRubyDir == "" ? "" : Files.readAllLines(Paths.ge
228228
def customJRubyTar = customJRubyDir == "" ? "" : (customJRubyDir + "/maven/jruby-dist/target/jruby-dist-${customJRubyVersion}-bin.tar.gz")
229229

230230
tasks.register("downloadJRuby", Download) {
231+
onlyIf { !project.hasProperty('skipJRubySetup') }
231232
description "Download JRuby artifact from this specific URL: ${jRubyURL}"
232233
src jRubyURL
233234
onlyIfNewer true

test-init.gradle

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)