From 85749ad6c9dedd77d922904543dac64990eee49c Mon Sep 17 00:00:00 2001 From: Callum Rogers Date: Mon, 13 Feb 2023 16:35:12 +0000 Subject: [PATCH] Parallelise some tasks (#1434) `createLaunchConfig`, `mergeDiagnosticsJson`, `createInitScript` and `createCheckScript` can all now run in parallel within the same project. --- changelog/@unreleased/pr-1434.v2.yml | 6 + gradle-sls-packaging/build.gradle | 2 + .../gradle/dist/service/Diagnostics.java | 18 +- .../service/DiagnosticsManifestPlugin.java | 2 +- .../dist/service/MergeDiagnosticsJson.java | 62 ++++ .../service/MergeDiagnosticsJsonTask.java | 42 +-- .../dist/service/tasks/CreateCheckScript.java | 59 ++++ .../service/tasks/CreateCheckScriptTask.java | 50 +-- .../dist/service/tasks/CreateInitScript.java | 48 +++ .../service/tasks/CreateInitScriptTask.java | 38 +-- .../dist/service/tasks/LaunchConfig.java | 295 ++++++++++++++++ .../dist/service/tasks/LaunchConfigTask.java | 315 +----------------- .../gradle/dist/service/tasks/ModuleArgs.java | 14 +- .../gradle/dist/service/util/EmitFiles.java | 10 +- .../JavaServiceDistributionPluginTests.groovy | 58 ++-- .../MainClassInferenceIntegrationSpec.groovy | 6 +- versions.lock | 1 + versions.props | 1 + 18 files changed, 533 insertions(+), 494 deletions(-) create mode 100644 changelog/@unreleased/pr-1434.v2.yml create mode 100644 gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJson.java create mode 100644 gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScript.java create mode 100644 gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScript.java create mode 100644 gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfig.java diff --git a/changelog/@unreleased/pr-1434.v2.yml b/changelog/@unreleased/pr-1434.v2.yml new file mode 100644 index 000000000..1f8e8d691 --- /dev/null +++ b/changelog/@unreleased/pr-1434.v2.yml @@ -0,0 +1,6 @@ +type: fix +fix: + description: '`createLaunchConfig`, `mergeDiagnosticsJson`, `createInitScript` and + `createCheckScript` can all now run in parallel within the same project.' + links: + - https://github.com/palantir/sls-packaging/pull/1434 diff --git a/gradle-sls-packaging/build.gradle b/gradle-sls-packaging/build.gradle index 7c844774a..5c130b4e5 100644 --- a/gradle-sls-packaging/build.gradle +++ b/gradle-sls-packaging/build.gradle @@ -23,6 +23,8 @@ dependencies { compileOnly 'org.immutables:value::annotations' annotationProcessor 'org.immutables:value' + compileOnly 'com.palantir.gradle.auto-parallelizable:auto-parallelizable-annotations' + annotationProcessor 'com.palantir.gradle.auto-parallelizable:auto-parallelizable' testImplementation gradleTestKit() testImplementation 'com.netflix.nebula:nebula-test' diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/Diagnostics.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/Diagnostics.java index 804c09fb1..adacf3a83 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/Diagnostics.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/Diagnostics.java @@ -21,34 +21,24 @@ import com.palantir.gradle.dist.ObjectMappers; import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Path; import java.util.List; import org.gradle.api.GradleException; -import org.gradle.api.Project; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public final class Diagnostics { - private static final Logger log = LoggerFactory.getLogger(Diagnostics.class); private static final String EXAMPLE = "[{\"type\":\"foo.v1\", \"docs\":\"...\"}, \"{\"type\":\"bar.v1\", " + "\"docs\":\"...\"}]"; - public static List parse(Project proj, File file) { - Path relativePath = proj.getRootDir().toPath().relativize(file.toPath()); + public static List parse(File file) { String string = null; try { - string = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8).trim(); - List value = - ObjectMappers.jsonMapper.readValue(string, new TypeReference>() {}); - log.info("Deserialized '{}': '{}'", relativePath, value); - return value; + string = Files.readString(file.toPath()).trim(); + return ObjectMappers.jsonMapper.readValue(string, new TypeReference<>() {}); } catch (IOException e) { throw new GradleException( String.format( "Failed to deserialize '%s', expecting something like '%s' but was '%s'", - relativePath, EXAMPLE, string), + file.getAbsolutePath(), EXAMPLE, string), e); } } diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/DiagnosticsManifestPlugin.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/DiagnosticsManifestPlugin.java index a11683be3..714358f97 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/DiagnosticsManifestPlugin.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/DiagnosticsManifestPlugin.java @@ -87,7 +87,7 @@ public void apply(Project project) { "diagnostics", mergeDiagnosticsTask .flatMap(MergeDiagnosticsJsonTask::getOutputJsonFile) - .map(file -> Diagnostics.parse(project, file.getAsFile()))); + .map(file -> Diagnostics.parse(file.getAsFile()))); }); project.getTasks().named("createManifest", CreateManifestTask.class).configure(createManifestTask -> { createManifestTask.dependsOn(mergeDiagnosticsJson); diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJson.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJson.java new file mode 100644 index 000000000..ec5a535fd --- /dev/null +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJson.java @@ -0,0 +1,62 @@ +/* + * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.dist.service; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.palantir.gradle.autoparallelizable.AutoParallelizable; +import com.palantir.gradle.dist.ObjectMappers; +import java.io.File; +import java.io.IOException; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import org.gradle.api.GradleException; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; + +@AutoParallelizable +final class MergeDiagnosticsJson { + interface Params { + @InputFiles + @PathSensitive(PathSensitivity.NONE) + ConfigurableFileCollection getClasspath(); + + @OutputFile + RegularFileProperty getOutputJsonFile(); + } + + static void action(Params params) { + List aggregated = params.getClasspath().getFiles().stream() + .flatMap(file -> Diagnostics.parse(file).stream()) + .distinct() + .sorted(Comparator.comparing(node -> node.get("type").asText())) + .collect(Collectors.toList()); + + File out = params.getOutputJsonFile().getAsFile().get(); + try { + ObjectMappers.jsonMapper.writeValue(out, aggregated); + } catch (IOException e) { + throw new GradleException("Failed to write " + out, e); + } + } + + private MergeDiagnosticsJson() {} +} diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJsonTask.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJsonTask.java index 61a41d442..96a0b1a8d 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJsonTask.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/MergeDiagnosticsJsonTask.java @@ -16,47 +16,7 @@ package com.palantir.gradle.dist.service; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.palantir.gradle.dist.ObjectMappers; -import java.io.File; -import java.io.IOException; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; -import org.gradle.api.DefaultTask; -import org.gradle.api.GradleException; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.file.RegularFileProperty; import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; -import org.gradle.api.tasks.TaskAction; @CacheableTask -public abstract class MergeDiagnosticsJsonTask extends DefaultTask { - - @InputFiles - @PathSensitive(PathSensitivity.NONE) - public abstract ConfigurableFileCollection getClasspath(); - - @OutputFile - public abstract RegularFileProperty getOutputJsonFile(); - - @TaskAction - public final void taskAction() { - List aggregated = getClasspath().getFiles().stream() - .flatMap(file -> Diagnostics.parse(getProject(), file).stream()) - .distinct() - .sorted(Comparator.comparing(node -> node.get("type").asText())) - .collect(Collectors.toList()); - - File out = getOutputJsonFile().getAsFile().get(); - try { - ObjectMappers.jsonMapper.writeValue(out, aggregated); - } catch (IOException e) { - throw new GradleException("Failed to write " + out, e); - } - } -} +public abstract class MergeDiagnosticsJsonTask extends MergeDiagnosticsJsonTaskImpl {} diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScript.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScript.java new file mode 100644 index 000000000..b6592caf7 --- /dev/null +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScript.java @@ -0,0 +1,59 @@ +/* + * (c) Copyright 2016 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.dist.service.tasks; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; +import com.palantir.gradle.autoparallelizable.AutoParallelizable; +import com.palantir.gradle.dist.service.JavaServiceDistributionPlugin; +import com.palantir.gradle.dist.service.util.EmitFiles; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.OutputFile; + +@AutoParallelizable +public final class CreateCheckScript { + interface Params { + @Input + Property getServiceName(); + + @Input + ListProperty getCheckArgs(); + + @OutputFile + RegularFileProperty getOutputFile(); + } + + static void action(Params params) { + if (!params.getCheckArgs().get().isEmpty()) { + EmitFiles.replaceVars( + JavaServiceDistributionPlugin.class.getResourceAsStream("/check.sh"), + params.getOutputFile().get().getAsFile().toPath(), + ImmutableMap.of( + "@serviceName@", params.getServiceName().get(), + "@checkArgs@", + Joiner.on(" ") + .join(params.getCheckArgs().get()))) + .toFile() + .setExecutable(true); + } + } + + private CreateCheckScript() {} +} diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScriptTask.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScriptTask.java index 8c55e0b1b..d8c049bdf 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScriptTask.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateCheckScriptTask.java @@ -16,54 +16,8 @@ package com.palantir.gradle.dist.service.tasks; -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableMap; -import com.palantir.gradle.dist.service.JavaServiceDistributionPlugin; -import com.palantir.gradle.dist.service.util.EmitFiles; -import java.io.IOException; -import org.gradle.api.DefaultTask; -import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.provider.ListProperty; -import org.gradle.api.provider.Property; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; - -public class CreateCheckScriptTask extends DefaultTask { - private final Property serviceName = getProject().getObjects().property(String.class); - private final ListProperty checkArgs = getProject().getObjects().listProperty(String.class); - private final RegularFileProperty outputFile = getProject().getObjects().fileProperty(); - +public abstract class CreateCheckScriptTask extends CreateCheckScriptTaskImpl { public CreateCheckScriptTask() { - outputFile.set(getProject().getLayout().getBuildDirectory().file("monitoring/check.sh")); - } - - @Input - public final Property getServiceName() { - return serviceName; - } - - @Input - public final ListProperty getCheckArgs() { - return checkArgs; - } - - @OutputFile - public final RegularFileProperty getOutputFile() { - return outputFile; - } - - @TaskAction - final void createInitScript() throws IOException { - if (!checkArgs.get().isEmpty()) { - EmitFiles.replaceVars( - JavaServiceDistributionPlugin.class.getResourceAsStream("/check.sh"), - getOutputFile().get().getAsFile().toPath(), - ImmutableMap.of( - "@serviceName@", serviceName.get(), - "@checkArgs@", Joiner.on(" ").join(checkArgs.get()))) - .toFile() - .setExecutable(true); - } + getOutputFile().set(getProject().getLayout().getBuildDirectory().file("monitoring/check.sh")); } } diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScript.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScript.java new file mode 100644 index 000000000..6747482d8 --- /dev/null +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScript.java @@ -0,0 +1,48 @@ +/* + * (c) Copyright 2016 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.dist.service.tasks; + +import com.google.common.collect.ImmutableMap; +import com.palantir.gradle.autoparallelizable.AutoParallelizable; +import com.palantir.gradle.dist.service.JavaServiceDistributionPlugin; +import com.palantir.gradle.dist.service.util.EmitFiles; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.OutputFile; + +@AutoParallelizable +public final class CreateInitScript { + interface Params { + @Input + Property getServiceName(); + + @OutputFile + RegularFileProperty getOutputFile(); + } + + static void action(Params params) { + EmitFiles.replaceVars( + JavaServiceDistributionPlugin.class.getResourceAsStream("/init.sh"), + params.getOutputFile().get().getAsFile().toPath(), + ImmutableMap.of("@serviceName@", params.getServiceName().get())) + .toFile() + .setExecutable(true); + } + + private CreateInitScript() {} +} diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScriptTask.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScriptTask.java index 8a5096dcd..81ea887bb 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScriptTask.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/CreateInitScriptTask.java @@ -16,42 +16,8 @@ package com.palantir.gradle.dist.service.tasks; -import com.google.common.collect.ImmutableMap; -import com.palantir.gradle.dist.service.JavaServiceDistributionPlugin; -import com.palantir.gradle.dist.service.util.EmitFiles; -import java.io.IOException; -import org.gradle.api.DefaultTask; -import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.provider.Property; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; - -public class CreateInitScriptTask extends DefaultTask { - private final Property serviceName = getProject().getObjects().property(String.class); - private final RegularFileProperty outputFile = getProject().getObjects().fileProperty(); - +public abstract class CreateInitScriptTask extends CreateInitScriptTaskImpl { public CreateInitScriptTask() { - outputFile.set(getProject().getLayout().getBuildDirectory().file("scripts/init.sh")); - } - - @Input - public final Property getServiceName() { - return serviceName; - } - - @OutputFile - public final RegularFileProperty getOutputFile() { - return outputFile; - } - - @TaskAction - final void createInitScript() throws IOException { - EmitFiles.replaceVars( - JavaServiceDistributionPlugin.class.getResourceAsStream("/init.sh"), - getOutputFile().get().getAsFile().toPath(), - ImmutableMap.of("@serviceName@", serviceName.get())) - .toFile() - .setExecutable(true); + getOutputFile().set(getProject().getLayout().getBuildDirectory().file("scripts/init.sh")); } } diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfig.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfig.java new file mode 100644 index 000000000..8c0a7cd24 --- /dev/null +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfig.java @@ -0,0 +1,295 @@ +/* + * (c) Copyright 2016 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.dist.service.tasks; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.palantir.gradle.autoparallelizable.AutoParallelizable; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import org.gradle.api.JavaVersion; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.OutputFile; +import org.immutables.value.Value; + +@AutoParallelizable +public final class LaunchConfig { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(new YAMLFactory()); + private static final ImmutableList java8gcLoggingOptions = ImmutableList.of( + "-XX:+PrintGCDateStamps", + "-XX:+PrintGCDetails", + "-XX:-TraceClassUnloading", + "-XX:+UseGCLogFileRotation", + "-XX:GCLogFileSize=10M", + "-XX:NumberOfGCLogFiles=10", + "-Xloggc:var/log/gc-%t-%p.log", + "-verbose:gc"); + private static final ImmutableList java14PlusOptions = + ImmutableList.of("-XX:+ShowCodeDetailsInExceptionMessages"); + private static final ImmutableList java15Options = + ImmutableList.of("-XX:+UnlockDiagnosticVMOptions", "-XX:+ExpandSubTypeCheckAtParseTime"); + private static final ImmutableList disableBiasedLocking = ImmutableList.of("-XX:-UseBiasedLocking"); + // Disable C2 compilation for problematic structure in JDK 11.0.16, see https://bugs.openjdk.org/browse/JDK-8291665 + private static final ImmutableList jdk11DisableC2Compile = + ImmutableList.of("-XX:CompileCommand=exclude,sun/security/ssl/SSLEngineInputRecord.decodeInputRecord"); + // UseContainerCpuShares was added in a patch release, thus IgnoreUnrecognizedVMOptions is required to avoid + // breaking distributions running with older JDKs. + private static final ImmutableList forceUseContainerCpuShares = + ImmutableList.of("-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UseContainerCpuShares"); + + private static final ImmutableList alwaysOnJvmOptions = ImmutableList.of( + "-XX:+CrashOnOutOfMemoryError", + "-Djava.io.tmpdir=var/data/tmp", + "-XX:ErrorFile=var/log/hs_err_pid%p.log", + "-XX:HeapDumpPath=var/log", + // Set DNS cache TTL to 20s to account for systems such as RDS and other + // AWS-managed systems that modify DNS records on failover. + "-Dsun.net.inetaddr.ttl=20", + "-XX:+UnlockDiagnosticVMOptions", + // Disable AVX-512 intrinsics due to AES/CTR corruption bug in https://bugs.openjdk.org/browse/JDK-8292158 + "-XX:+IgnoreUnrecognizedVMOptions", + // UseAVX is not recognized on some platforms (arm), so we must include 'IgnoreUnrecognizedVMOptions'. + // When a system supports UseAVX=N, setting UseAVX=N+1 will set the flag to the highest supported value. + "-XX:UseAVX=2", + "-XX:NativeMemoryTracking=summary", + // Increase default JFR stack depth beyond the default (conservative) 64 frames. + // This can be overridden by user-provided options. + // See sls-packaging#1230 + "-XX:FlightRecorderOptions=stackdepth=256"); + + // Reduce memory usage for some versions of glibc. + // Default value is 8 * CORES. + // See https://issues.apache.org/jira/browse/HADOOP-7154 + public static final Map defaultEnvironment = ImmutableMap.of("MALLOC_ARENA_MAX", "4"); + + interface Params { + @Input + Property getMainClass(); + + @Input + Property getServiceName(); + + @Input + ListProperty getGcJvmOptions(); + + @Input + Property getAddJava8GcLogging(); + + @Input + @Optional + Property getJavaHome(); + + @Input + Property getJavaVersion(); + + @Input + ListProperty getArgs(); + + @Input + ListProperty getCheckArgs(); + + @Input + ListProperty getDefaultJvmOpts(); + + @Input + MapProperty getEnv(); + + @InputFiles + ConfigurableFileCollection getClasspath(); + + /** + * The difference between fullClasspath and classpath is that classpath is what is written + * to the launcher-static.yml file, this might in some cases be the manifest classpath + * JAR. Full Classpath on the other hand is always going to be the full set of JARs which may + * be the same as classpath if manifest classpath JARs are not used. + */ + @InputFiles + ConfigurableFileCollection getFullClasspath(); + + @InputFiles + ConfigurableFileCollection getJavaAgents(); + + @OutputFile + RegularFileProperty getStaticLauncher(); + + @OutputFile + RegularFileProperty getCheckLauncher(); + } + + static void action(Params params) { + JavaVersion javaVersion = params.getJavaVersion().get(); + + writeConfig( + LaunchConfigInfo.builder() + .mainClass(params.getMainClass().get()) + .serviceName(params.getServiceName().get()) + .javaHome(params.getJavaHome().getOrElse("")) + .args(params.getArgs().get()) + .classpath(relativizeToServiceLibDirectory(params.getClasspath())) + .addAllJvmOpts(javaAgentArgs(params)) + .addAllJvmOpts(alwaysOnJvmOptions) + .addAllJvmOpts(params.getAddJava8GcLogging().get() ? java8gcLoggingOptions : ImmutableList.of()) + // Java 11.0.16 introduced a potential memory leak issues when using the C2 + // compiler + .addAllJvmOpts( + javaVersion.compareTo(JavaVersion.toVersion("11")) == 0 + ? jdk11DisableC2Compile + : ImmutableList.of()) + .addAllJvmOpts( + javaVersion.compareTo(JavaVersion.toVersion("14")) >= 0 + ? java14PlusOptions + : ImmutableList.of()) + .addAllJvmOpts( + javaVersion.compareTo(JavaVersion.toVersion("15")) == 0 + ? java15Options + : ImmutableList.of()) + // Biased locking is disabled on java 15+ https://openjdk.java.net/jeps/374 + // We disable biased locking on all releases in order to reduce safepoint time, + // revoking biased locks requires a safepoint, and can occur for non-obvious + // reasons, e.g. System.identityHashCode. + .addAllJvmOpts( + javaVersion.compareTo(JavaVersion.toVersion("15")) < 0 + ? disableBiasedLocking + : ImmutableList.of()) + // https://bugs.openjdk.org/browse/JDK-8281181 stopped respecting cpu.shares for + // processor count. UseContainerCpuShares can be enabled for the time being, however it + // is deprecated in jdk19 and obsoleted in jdk20: https://bugs.openjdk.org/browse/JDK-8282684 + .addAllJvmOpts( + javaVersion.compareTo(JavaVersion.toVersion("11")) >= 0 + && javaVersion.compareTo(JavaVersion.toVersion("19")) <= 0 + ? forceUseContainerCpuShares + : ImmutableList.of()) + .addAllJvmOpts(ModuleArgs.collectClasspathArgs(javaVersion, params.getFullClasspath())) + .addAllJvmOpts(params.getGcJvmOptions().get()) + .addAllJvmOpts(params.getDefaultJvmOpts().get()) + .putAllEnv(defaultEnvironment) + .putAllEnv(params.getEnv().get()) + .build(), + params.getStaticLauncher().get().getAsFile()); + + writeConfig( + LaunchConfigInfo.builder() + .mainClass(params.getMainClass().get()) + .serviceName(params.getServiceName().get()) + .javaHome(params.getJavaHome().getOrElse("")) + .args(params.getCheckArgs().get()) + .classpath(relativizeToServiceLibDirectory(params.getClasspath())) + .addAllJvmOpts(javaAgentArgs(params)) + .addAllJvmOpts(alwaysOnJvmOptions) + .addAllJvmOpts(params.getDefaultJvmOpts().get()) + .env(defaultEnvironment) + .build(), + params.getCheckLauncher().get().getAsFile()); + } + + private static void writeConfig(LaunchConfigInfo config, File scriptFile) { + try { + Files.createDirectories(scriptFile.getParentFile().toPath()); + OBJECT_MAPPER.writeValue(scriptFile, config); + } catch (IOException e) { + throw new RuntimeException("Failed to write config", e); + } + } + + private static List javaAgentArgs(Params params) { + return params.getJavaAgents().getFiles().stream() + .map(file -> "-javaagent:service/lib/agent/" + + validateJavaAgent(file).getName()) + .collect(Collectors.toList()); + } + + /** Returns the input file. An exception is thrown if the {@code agentFile} is not a java agent. */ + private static File validateJavaAgent(File agentFile) { + try { + JarFile agentJarFile = new JarFile(agentFile); + if (!agentJarFile.getManifest().getMainAttributes().containsKey(new Attributes.Name("Premain-Class"))) { + throw new IllegalArgumentException("Jar file " + agentFile.getName() + + " is not a java agent and contains no Premain-Class manifest entry"); + } + return agentFile; + } catch (IOException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + private static List relativizeToServiceLibDirectory(FileCollection files) { + return files.getFiles().stream() + .map(file -> "service/lib/" + file.getName()) + .collect(Collectors.toList()); + } + + @Value.Immutable + @JsonSerialize(as = ImmutableLaunchConfigInfo.class) + @JsonDeserialize(as = ImmutableLaunchConfigInfo.class) + public interface LaunchConfigInfo { + // keep in sync with StaticLaunchConfig struct in go-java-launcher + @Value.Default + default String configType() { + return "java"; + } + + @Value.Default + default int configVersion() { + return 1; + } + + @Value.Default + default List dirs() { + return ImmutableList.of("var/data/tmp"); + } + + String mainClass(); + + String serviceName(); + + String javaHome(); + + List classpath(); + + List jvmOpts(); + + List args(); + + Map env(); + + static Builder builder() { + return new Builder(); + } + + final class Builder extends ImmutableLaunchConfigInfo.Builder {} + } + + private LaunchConfig() {} +} diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfigTask.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfigTask.java index f351435cc..f075280e1 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfigTask.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/LaunchConfigTask.java @@ -16,318 +16,9 @@ package com.palantir.gradle.dist.service.tasks; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.List; -import java.util.Map; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.stream.Collectors; -import org.gradle.api.DefaultTask; -import org.gradle.api.JavaVersion; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.file.FileCollection; -import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.provider.ListProperty; -import org.gradle.api.provider.MapProperty; -import org.gradle.api.provider.Property; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; -import org.immutables.value.Value; - -public abstract class LaunchConfigTask extends DefaultTask { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(new YAMLFactory()); - private static final ImmutableList java8gcLoggingOptions = ImmutableList.of( - "-XX:+PrintGCDateStamps", - "-XX:+PrintGCDetails", - "-XX:-TraceClassUnloading", - "-XX:+UseGCLogFileRotation", - "-XX:GCLogFileSize=10M", - "-XX:NumberOfGCLogFiles=10", - "-Xloggc:var/log/gc-%t-%p.log", - "-verbose:gc"); - private static final ImmutableList java14PlusOptions = - ImmutableList.of("-XX:+ShowCodeDetailsInExceptionMessages"); - private static final ImmutableList java15Options = - ImmutableList.of("-XX:+UnlockDiagnosticVMOptions", "-XX:+ExpandSubTypeCheckAtParseTime"); - private static final ImmutableList disableBiasedLocking = ImmutableList.of("-XX:-UseBiasedLocking"); - // Disable C2 compilation for problematic structure in JDK 11.0.16, see https://bugs.openjdk.org/browse/JDK-8291665 - private static final ImmutableList jdk11DisableC2Compile = - ImmutableList.of("-XX:CompileCommand=exclude,sun/security/ssl/SSLEngineInputRecord.decodeInputRecord"); - // UseContainerCpuShares was added in a patch release, thus IgnoreUnrecognizedVMOptions is required to avoid - // breaking distributions running with older JDKs. - private static final ImmutableList forceUseContainerCpuShares = - ImmutableList.of("-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UseContainerCpuShares"); - - private static final ImmutableList alwaysOnJvmOptions = ImmutableList.of( - "-XX:+CrashOnOutOfMemoryError", - "-Djava.io.tmpdir=var/data/tmp", - "-XX:ErrorFile=var/log/hs_err_pid%p.log", - "-XX:HeapDumpPath=var/log", - // Set DNS cache TTL to 20s to account for systems such as RDS and other - // AWS-managed systems that modify DNS records on failover. - "-Dsun.net.inetaddr.ttl=20", - "-XX:+UnlockDiagnosticVMOptions", - // Disable AVX-512 intrinsics due to AES/CTR corruption bug in https://bugs.openjdk.org/browse/JDK-8292158 - "-XX:+IgnoreUnrecognizedVMOptions", - // UseAVX is not recognized on some platforms (arm), so we must include 'IgnoreUnrecognizedVMOptions'. - // When a system supports UseAVX=N, setting UseAVX=N+1 will set the flag to the highest supported value. - "-XX:UseAVX=2", - "-XX:NativeMemoryTracking=summary", - // Increase default JFR stack depth beyond the default (conservative) 64 frames. - // This can be overridden by user-provided options. - // See sls-packaging#1230 - "-XX:FlightRecorderOptions=stackdepth=256"); - - // Reduce memory usage for some versions of glibc. - // Default value is 8 * CORES. - // See https://issues.apache.org/jira/browse/HADOOP-7154 - public static final Map defaultEnvironment = ImmutableMap.of("MALLOC_ARENA_MAX", "4"); - - private final Property mainClass = getProject().getObjects().property(String.class); - private final Property serviceName = getProject().getObjects().property(String.class); - private final ListProperty gcJvmOptions = getProject().getObjects().listProperty(String.class); - private final Property addJava8GcLogging = - getProject().getObjects().property(Boolean.class); - private final Property javaHome = getProject().getObjects().property(String.class); - private final Property javaVersion = getProject().getObjects().property(JavaVersion.class); - private final ListProperty args = getProject().getObjects().listProperty(String.class); - private final ListProperty checkArgs = getProject().getObjects().listProperty(String.class); - private final ListProperty defaultJvmOpts = - getProject().getObjects().listProperty(String.class); - - private final MapProperty env = getProject().getObjects().mapProperty(String.class, String.class); - private RegularFileProperty staticLauncher = getProject().getObjects().fileProperty(); - private RegularFileProperty checkLauncher = getProject().getObjects().fileProperty(); - - @SuppressWarnings("PublicConstructorForAbstractClass") +public abstract class LaunchConfigTask extends LaunchConfigTaskImpl { public LaunchConfigTask() { - staticLauncher.set(getProject().getLayout().getBuildDirectory().file("scripts/launcher-static.yml")); - checkLauncher.set(getProject().getLayout().getBuildDirectory().file("scripts/launcher-check.yml")); - } - - @Input - public final Property getMainClass() { - return mainClass; - } - - @Input - public final Property getServiceName() { - return serviceName; - } - - @Input - public final ListProperty getGcJvmOptions() { - return gcJvmOptions; - } - - @Input - public final Property getAddJava8GcLogging() { - return addJava8GcLogging; - } - - @Input - @Optional - public final Property getJavaHome() { - return javaHome; - } - - @Input - public final Property getJavaVersion() { - return javaVersion; - } - - @Input - public final ListProperty getArgs() { - return args; - } - - @Input - public final ListProperty getCheckArgs() { - return checkArgs; - } - - @Input - public final ListProperty getDefaultJvmOpts() { - return defaultJvmOpts; - } - - @Input - public final MapProperty getEnv() { - return env; - } - - @InputFiles - public abstract ConfigurableFileCollection getClasspath(); - - /** - * The difference between fullClasspath and classpath is that classpath is what is written - * to the launcher-static.yml file, this might in some cases be the manifest classpath - * JAR. Full Classpath on the other hand is always going to be the full set of JARs which may - * be the same as classpath if manifest classpath JARs are not used. - */ - @InputFiles - public abstract ConfigurableFileCollection getFullClasspath(); - - @InputFiles - public abstract ConfigurableFileCollection getJavaAgents(); - - @OutputFile - public final RegularFileProperty getStaticLauncher() { - return staticLauncher; - } - - @OutputFile - public final RegularFileProperty getCheckLauncher() { - return checkLauncher; - } - - @TaskAction - public final void createConfig() throws IOException { - writeConfig( - LaunchConfig.builder() - .mainClass(mainClass.get()) - .serviceName(serviceName.get()) - .javaHome(javaHome.getOrElse("")) - .args(args.get()) - .classpath(relativizeToServiceLibDirectory(getClasspath())) - .addAllJvmOpts(javaAgentArgs()) - .addAllJvmOpts(alwaysOnJvmOptions) - .addAllJvmOpts(addJava8GcLogging.get() ? java8gcLoggingOptions : ImmutableList.of()) - // Java 11.0.16 introduced a potential memory leak issues when using the C2 - // compiler - .addAllJvmOpts( - javaVersion.get().compareTo(JavaVersion.toVersion("11")) == 0 - ? jdk11DisableC2Compile - : ImmutableList.of()) - .addAllJvmOpts( - javaVersion.get().compareTo(JavaVersion.toVersion("14")) >= 0 - ? java14PlusOptions - : ImmutableList.of()) - .addAllJvmOpts( - javaVersion.get().compareTo(JavaVersion.toVersion("15")) == 0 - ? java15Options - : ImmutableList.of()) - // Biased locking is disabled on java 15+ https://openjdk.java.net/jeps/374 - // We disable biased locking on all releases in order to reduce safepoint time, - // revoking biased locks requires a safepoint, and can occur for non-obvious - // reasons, e.g. System.identityHashCode. - .addAllJvmOpts( - javaVersion.get().compareTo(JavaVersion.toVersion("15")) < 0 - ? disableBiasedLocking - : ImmutableList.of()) - // https://bugs.openjdk.org/browse/JDK-8281181 stopped respecting cpu.shares for - // processor count. UseContainerCpuShares can be enabled for the time being, however it - // is deprecated in jdk19 and obsoleted in jdk20: https://bugs.openjdk.org/browse/JDK-8282684 - .addAllJvmOpts( - javaVersion.get().compareTo(JavaVersion.toVersion("11")) >= 0 - && javaVersion.get().compareTo(JavaVersion.toVersion("19")) <= 0 - ? forceUseContainerCpuShares - : ImmutableList.of()) - .addAllJvmOpts( - ModuleArgs.collectClasspathArgs(getProject(), javaVersion.get(), getFullClasspath())) - .addAllJvmOpts(gcJvmOptions.get()) - .addAllJvmOpts(defaultJvmOpts.get()) - .putAllEnv(defaultEnvironment) - .putAllEnv(env.get()) - .build(), - getStaticLauncher().get().getAsFile()); - - writeConfig( - LaunchConfig.builder() - .mainClass(mainClass.get()) - .serviceName(serviceName.get()) - .javaHome(javaHome.getOrElse("")) - .args(checkArgs.get()) - .classpath(relativizeToServiceLibDirectory(getClasspath())) - .addAllJvmOpts(javaAgentArgs()) - .addAllJvmOpts(alwaysOnJvmOptions) - .addAllJvmOpts(defaultJvmOpts.get()) - .env(defaultEnvironment) - .build(), - getCheckLauncher().get().getAsFile()); - } - - private static void writeConfig(LaunchConfig config, File scriptFile) throws IOException { - Files.createDirectories(scriptFile.getParentFile().toPath()); - OBJECT_MAPPER.writeValue(scriptFile, config); - } - - private List javaAgentArgs() { - return getJavaAgents().getFiles().stream() - .map(file -> "-javaagent:service/lib/agent/" - + validateJavaAgent(file).getName()) - .collect(Collectors.toList()); - } - - /** Returns the input file. An exception is thrown if the {@code agentFile} is not a java agent. */ - private static File validateJavaAgent(File agentFile) { - try { - JarFile agentJarFile = new JarFile(agentFile); - if (!agentJarFile.getManifest().getMainAttributes().containsKey(new Attributes.Name("Premain-Class"))) { - throw new IllegalArgumentException("Jar file " + agentFile.getName() - + " is not a java agent and contains no Premain-Class manifest entry"); - } - return agentFile; - } catch (IOException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - - private static List relativizeToServiceLibDirectory(FileCollection files) { - return files.getFiles().stream() - .map(file -> "service/lib/" + file.getName()) - .collect(Collectors.toList()); - } - - @Value.Immutable - @JsonSerialize(as = ImmutableLaunchConfig.class) - @JsonDeserialize(as = ImmutableLaunchConfig.class) - public interface LaunchConfig { - // keep in sync with StaticLaunchConfig struct in go-java-launcher - @Value.Default - default String configType() { - return "java"; - } - - @Value.Default - default int configVersion() { - return 1; - } - - @Value.Default - default List dirs() { - return ImmutableList.of("var/data/tmp"); - } - - String mainClass(); - - String serviceName(); - - String javaHome(); - - List classpath(); - - List jvmOpts(); - - List args(); - - Map env(); - - static Builder builder() { - return new Builder(); - } - - final class Builder extends ImmutableLaunchConfig.Builder {} + getStaticLauncher().set(getProject().getLayout().getBuildDirectory().file("scripts/launcher-static.yml")); + getCheckLauncher().set(getProject().getLayout().getBuildDirectory().file("scripts/launcher-check.yml")); } } diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/ModuleArgs.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/ModuleArgs.java index 2a7c39c3a..8e61f57a2 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/ModuleArgs.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/tasks/ModuleArgs.java @@ -27,8 +27,9 @@ import java.util.stream.Stream; import javax.annotation.Nullable; import org.gradle.api.JavaVersion; -import org.gradle.api.Project; import org.gradle.api.file.FileCollection; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; import org.immutables.value.Value; /** @@ -40,6 +41,7 @@ * plugin gradle-baseline#1944. */ final class ModuleArgs { + private static final Logger log = Logging.getLogger(ModuleArgs.class); private static final String ADD_EXPORTS_ATTRIBUTE = "Add-Exports"; private static final String ADD_OPENS_ATTRIBUTE = "Add-Opens"; @@ -53,8 +55,7 @@ final class ModuleArgs { // that we aren't aware of. private static final ImmutableList DEFAULT_EXPORTS = ImmutableList.of("java.management/sun.management"); - static ImmutableList collectClasspathArgs( - Project project, JavaVersion javaVersion, FileCollection classpath) { + static ImmutableList collectClasspathArgs(JavaVersion javaVersion, FileCollection classpath) { // --add-exports is unnecessary prior to java 16 if (javaVersion.compareTo(JavaVersion.toVersion("16")) < 0) { return ImmutableList.of(); @@ -67,16 +68,15 @@ static ImmutableList collectClasspathArgs( try (JarFile jar = new JarFile(file)) { java.util.jar.Manifest maybeJarManifest = jar.getManifest(); Optional parsedModuleInfo = parseModuleInfo(maybeJarManifest); - project.getLogger() - .debug("Jar '{}' produced manifest info: {}", file, parsedModuleInfo); + log.debug("Jar '{}' produced manifest info: {}", file, parsedModuleInfo); return parsedModuleInfo.orElse(null); } } else { - project.getLogger().info("File {} wasn't a JAR or file", file); + log.info("File {} wasn't a JAR or file", file); } return null; } catch (IOException e) { - project.getLogger().warn("Failed to check jar {} for manifest attributes", file, e); + log.warn("Failed to check jar {} for manifest attributes", file, e); return null; } }) diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/util/EmitFiles.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/util/EmitFiles.java index 58afb43f8..37197d68e 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/util/EmitFiles.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/service/util/EmitFiles.java @@ -26,10 +26,12 @@ import java.util.Map; public final class EmitFiles { - public static Path replaceVars(InputStream src, Path dest, Map vars) throws IOException { + public static Path replaceVars(InputStream src, Path dest, Map vars) { String text; try (Reader reader = new InputStreamReader(src, StandardCharsets.UTF_8)) { text = CharStreams.toString(reader); + } catch (IOException e) { + throw new RuntimeException("Failed to read template", e); } for (Map.Entry entry : vars.entrySet()) { @@ -40,7 +42,11 @@ public static Path replaceVars(InputStream src, Path dest, Map v dest.getParent().toFile().mkdirs(); // write content - return Files.write(dest, text.getBytes(StandardCharsets.UTF_8)); + try { + return Files.write(dest, text.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new RuntimeException("Failed to write templated file", e); + } } private EmitFiles() {} diff --git a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy index d97e3ecee..ef7bc9c09 100644 --- a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy +++ b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy @@ -21,18 +21,16 @@ import com.fasterxml.jackson.datatype.guava.GuavaModule import com.palantir.gradle.dist.GradleIntegrationSpec import com.palantir.gradle.dist.SlsManifest import com.palantir.gradle.dist.Versions -import com.palantir.gradle.dist.service.tasks.LaunchConfigTask +import com.palantir.gradle.dist.service.tasks.LaunchConfig import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.TaskOutcome +import org.junit.Assert +import spock.lang.Unroll import java.util.jar.Attributes import java.util.jar.JarOutputStream import java.util.jar.Manifest -import spock.lang.Unroll - import java.util.zip.ZipFile -import org.gradle.testkit.runner.TaskOutcome -import org.junit.Assert - import java.util.zip.ZipOutputStream class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { @@ -394,7 +392,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { runTasks(':build', ':distTar', ':untar') then: - def expectedStaticConfig = LaunchConfigTask.LaunchConfig.builder() + def expectedStaticConfig = LaunchConfig.LaunchConfigInfo.builder() .mainClass("test.Test") .serviceName("service-name") .javaHome("foo") @@ -414,15 +412,15 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { '-XX:+UseParallelGC', '-Xmx4M', '-Djavax.net.ssl.trustStore=truststore.jks']) - .env(LaunchConfigTask.defaultEnvironment + [ + .env(LaunchConfig.defaultEnvironment + [ "key1": "val1", "key2": "val2"]) .dirs(["var/data/tmp"]) .build() def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) - def expectedCheckConfig = LaunchConfigTask.LaunchConfig.builder() + def expectedCheckConfig = LaunchConfig.LaunchConfigInfo.builder() .mainClass(actualStaticConfig.mainClass()) .serviceName(actualStaticConfig.serviceName()) .javaHome(actualStaticConfig.javaHome()) @@ -441,12 +439,12 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { '-XX:FlightRecorderOptions=stackdepth=256', '-Xmx4M', '-Djavax.net.ssl.trustStore=truststore.jks']) - .env(LaunchConfigTask.defaultEnvironment) + .env(LaunchConfig.defaultEnvironment) .dirs(actualStaticConfig.dirs()) .build() def actualCheckConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-check.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-check.yml'), LaunchConfig.LaunchConfigInfo) expectedCheckConfig == actualCheckConfig } @@ -465,7 +463,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { runTasks(':build', ':distTar', ':untar') then: - def expectedStaticConfig = LaunchConfigTask.LaunchConfig.builder() + def expectedStaticConfig = LaunchConfig.LaunchConfigInfo.builder() .mainClass("test.Test") .serviceName("service-name") .javaHome("foo") @@ -497,7 +495,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { .env(["MALLOC_ARENA_MAX": '4']) .build() def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) expectedStaticConfig == actualStaticConfig } @@ -517,7 +515,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) actualStaticConfig.jvmOpts().containsAll([ "-XX:+UseShenandoahGC", "-XX:+ExplicitGCInvokesConcurrent", @@ -845,17 +843,17 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { startScript.any { it.contains('/lib/mockito-core-2.7.22.jar') } // verify launcher YAML files - LaunchConfigTask.LaunchConfig launcherCheck = OBJECT_MAPPER.readValue( + LaunchConfig.LaunchConfigInfo launcherCheck = OBJECT_MAPPER.readValue( new File(projectDir, 'parent/dist/service-name-0.0.1/service/bin/launcher-check.yml'), - LaunchConfigTask.LaunchConfig.class) + LaunchConfig.LaunchConfigInfo.class) launcherCheck.classpath.any { it.contains('/lib/annotations-3.0.1.jar') } launcherCheck.classpath.any { it.contains('/lib/guava-19.0.jar') } launcherCheck.classpath.any { it.contains('/lib/mockito-core-2.7.22.jar') } - LaunchConfigTask.LaunchConfig launcherStatic = OBJECT_MAPPER.readValue( + LaunchConfig.LaunchConfigInfo launcherStatic = OBJECT_MAPPER.readValue( new File(projectDir, 'parent/dist/service-name-0.0.1/service/bin/launcher-static.yml'), - LaunchConfigTask.LaunchConfig.class) + LaunchConfig.LaunchConfigInfo.class) launcherStatic.classpath.any { it.contains('/lib/annotations-3.0.1.jar') } launcherStatic.classpath.any { it.contains('/lib/guava-19.0.jar') } @@ -992,15 +990,15 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { startScript.any { it.contains('-manifest-classpath-0.0.1.jar') } // verify launcher YAML files - LaunchConfigTask.LaunchConfig launcherCheck = OBJECT_MAPPER.readValue( + LaunchConfig.LaunchConfigInfo launcherCheck = OBJECT_MAPPER.readValue( new File(projectDir, 'parent/dist/service-name-0.0.1/service/bin/launcher-check.yml'), - LaunchConfigTask.LaunchConfig.class) + LaunchConfig.LaunchConfigInfo.class) launcherCheck.classpath.any { it.contains('-manifest-classpath-0.0.1.jar') } - LaunchConfigTask.LaunchConfig launcherStatic = OBJECT_MAPPER.readValue( + LaunchConfig.LaunchConfigInfo launcherStatic = OBJECT_MAPPER.readValue( new File(projectDir, 'parent/dist/service-name-0.0.1/service/bin/launcher-static.yml'), - LaunchConfigTask.LaunchConfig.class) + LaunchConfig.LaunchConfigInfo.class) launcherStatic.classpath.any { it.contains('-manifest-classpath-0.0.1.jar') } } @@ -1055,7 +1053,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) actualStaticConfig.jvmOpts.containsAll(['-XX:+UseParNewGC', '-XX:+UseConcMarkSweepGC', '-XX:CMSInitiatingOccupancyFraction=75']) } @@ -1088,7 +1086,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) actualStaticConfig.jvmOpts.containsAll(['-XX:+UseG1GC', '-XX:+UseNUMA']) } @@ -1110,7 +1108,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) actualStaticConfig.jvmOpts().contains("-javaagent:service/lib/agent/byte-buddy-agent-1.10.21.jar") fileExists('dist/service-name-0.0.1/service/lib/agent/byte-buddy-agent-1.10.21.jar') } @@ -1150,7 +1148,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) actualStaticConfig.jvmOpts().containsAll([ "--add-exports", "java.management/sun.management=ALL-UNNAMED" @@ -1183,7 +1181,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualOpts = OBJECT_MAPPER.readValue( file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), - LaunchConfigTask.LaunchConfig) + LaunchConfig.LaunchConfigInfo) .jvmOpts() // Quick check @@ -1222,7 +1220,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualOpts = OBJECT_MAPPER.readValue( file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), - LaunchConfigTask.LaunchConfig) + LaunchConfig.LaunchConfigInfo) .jvmOpts() // Quick check @@ -1262,7 +1260,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { then: def actualOpts = OBJECT_MAPPER.readValue( file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), - LaunchConfigTask.LaunchConfig) + LaunchConfig.LaunchConfigInfo) .jvmOpts() // Quick check diff --git a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/MainClassInferenceIntegrationSpec.groovy b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/MainClassInferenceIntegrationSpec.groovy index a33dcc3db..5fc19204f 100644 --- a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/MainClassInferenceIntegrationSpec.groovy +++ b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/MainClassInferenceIntegrationSpec.groovy @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.yaml.YAMLFactory import com.fasterxml.jackson.datatype.guava.GuavaModule import com.palantir.gradle.dist.GradleIntegrationSpec -import com.palantir.gradle.dist.service.tasks.LaunchConfigTask +import com.palantir.gradle.dist.service.tasks.LaunchConfig import org.gradle.testkit.runner.UnexpectedBuildFailure class MainClassInferenceIntegrationSpec extends GradleIntegrationSpec { @@ -69,7 +69,7 @@ class MainClassInferenceIntegrationSpec extends GradleIntegrationSpec { then: def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) actualStaticConfig.mainClass() == "test.Test" } @@ -110,7 +110,7 @@ class MainClassInferenceIntegrationSpec extends GradleIntegrationSpec { then: def actualStaticConfig = OBJECT_MAPPER.readValue( - file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfigTask.LaunchConfig) + file('dist/service-name-0.0.1/service/bin/launcher-static.yml'), LaunchConfig.LaunchConfigInfo) actualStaticConfig.mainClass() == "test.Test" } diff --git a/versions.lock b/versions.lock index 420342c6a..98b34c9ee 100644 --- a/versions.lock +++ b/versions.lock @@ -13,6 +13,7 @@ com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava (1 c com.google.j2objc:j2objc-annotations:1.3 (1 constraints: b809eda0) com.netflix.nebula:nebula-dependency-recommender:9.1.1 (1 constraints: bf1b4246) com.netflix.nebula:nebula-gradle-interop:1.0.11 (1 constraints: 9214098d) +com.palantir.gradle.auto-parallelizable:auto-parallelizable-annotations:1.1.0 (1 constraints: 0405f335) com.palantir.gradle.consistentversions:gradle-consistent-versions:1.27.0 (1 constraints: 3c05423b) com.palantir.safe-logging:logger:3.2.0 (1 constraints: be107db2) com.palantir.safe-logging:logger-slf4j:3.2.0 (1 constraints: 000e5942) diff --git a/versions.props b/versions.props index a4e80345a..ffb5acec8 100644 --- a/versions.props +++ b/versions.props @@ -1,6 +1,7 @@ com.fasterxml.jackson.*:* = 2.14.1 com.fasterxml.jackson.core:jackson-databind = 2.14.1 com.google.guava:guava = 31.1-jre +com.palantir.gradle.auto-parallelizable:* = 1.1.0 com.palantir.gradle.consistentversions:gradle-consistent-versions = 1.27.0 com.palantir.safe-logging:* = 3.2.0 com.palantir.sls.versions:sls-versions = 1.5.0