Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GraalVM download URL on Amazon Linux for AWS Lambda #1219

Merged
merged 3 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal AS graalvm
ENV LANG=en_US.UTF-8
RUN dnf update -y && dnf install -y gcc glibc-devel zlib-devel libstdc++-static tar && dnf clean all && rm -rf /var/cache/dnf
RUN curl -4 -L https://download.oracle.com/graalvm/17/archive/graalvm-jdk-17.0.12_linux-aarch64_bin.tar.gz -o /tmp/graalvm.tar.gz \
&& mkdir -p /usr/lib/graalvm \
&& tar -zxf /tmp/graalvm.tar.gz -C /usr/lib/graalvm --strip-components 1 \
&& rm -rf /tmp/*
ENV PATH="/usr/lib/graalvm/bin:${PATH}"
WORKDIR /home/app
COPY classes /home/app/classes
COPY dependency/* /home/app/libs/
COPY graalvm-reachability-metadat[a] /home/app/graalvm-reachability-metadata
COPY nativ[e]/generated /home/app/
COPY *.args /home/app/graalvm-native-image.args
RUN native-image @/home/app/graalvm-native-image.args -H:Class=io.micronaut.function.aws.runtime.MicronautLambdaRuntime -H:Name=application -cp "/home/app/libs/*:/home/app/classes/"

FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal
WORKDIR /function
RUN dnf update -y && dnf install -y zip && dnf clean all
COPY --from=graalvm /home/app/application /function/func
RUN echo "#!/bin/sh" >> bootstrap && echo "set -euo pipefail" >> bootstrap && echo "./func -XX:MaximumHeapSizePercent=80 -Dio.netty.allocator.numDirectArenas=0 -Dio.netty.noPreferDirect=true -Djava.library.path=$(pwd)" >> bootstrap
RUN chmod 777 bootstrap
RUN chmod 777 func
RUN zip -j function.zip bootstrap func
ENTRYPOINT ["/function/func"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal AS graalvm
ENV LANG=en_US.UTF-8
RUN dnf update -y && dnf install -y gcc glibc-devel zlib-devel libstdc++-static tar && dnf clean all && rm -rf /var/cache/dnf
RUN curl -4 -L https://download.oracle.com/graalvm/17/archive/graalvm-jdk-17.0.12_linux-x64_bin.tar.gz -o /tmp/graalvm.tar.gz \
&& mkdir -p /usr/lib/graalvm \
&& tar -zxf /tmp/graalvm.tar.gz -C /usr/lib/graalvm --strip-components 1 \
&& rm -rf /tmp/*
ENV PATH="/usr/lib/graalvm/bin:${PATH}"
WORKDIR /home/app
COPY classes /home/app/classes
COPY dependency/* /home/app/libs/
COPY graalvm-reachability-metadat[a] /home/app/graalvm-reachability-metadata
COPY nativ[e]/generated /home/app/
COPY *.args /home/app/graalvm-native-image.args
RUN native-image @/home/app/graalvm-native-image.args -H:Class=io.micronaut.function.aws.runtime.MicronautLambdaRuntime -H:Name=application -cp "/home/app/libs/*:/home/app/classes/"

FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal
WORKDIR /function
RUN dnf update -y && dnf install -y zip && dnf clean all
COPY --from=graalvm /home/app/application /function/func
RUN echo "#!/bin/sh" >> bootstrap && echo "set -euo pipefail" >> bootstrap && echo "./func -XX:MaximumHeapSizePercent=80 -Dio.netty.allocator.numDirectArenas=0 -Dio.netty.noPreferDirect=true -Djava.library.path=$(pwd)" >> bootstrap
RUN chmod 777 bootstrap
RUN chmod 777 func
RUN zip -j function.zip bootstrap func
ENTRYPOINT ["/function/func"]
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM amazonlinux:2023 AS graalvm
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal AS graalvm
ENV LANG=en_US.UTF-8
RUN yum update -y && yum install -y gcc gcc-c++ glibc-devel curl-minimal bash zlib zlib-devel zlib-static zip tar gzip && yum clean all && rm -rf /var/cache/yum
RUN curl -4 -L https://download.oracle.com/graalvm/17/latest/graalvm-jdk-17_linux-x64_bin.tar.gz -o /tmp/graalvm.tar.gz \
RUN dnf update -y && dnf install -y gcc glibc-devel zlib-devel libstdc++-static tar && dnf clean all && rm -rf /var/cache/dnf
RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-aarch64_bin.tar.gz -o /tmp/graalvm.tar.gz \
&& mkdir -p /usr/lib/graalvm \
&& tar -zxf /tmp/graalvm.tar.gz -C /usr/lib/graalvm --strip-components 1 \
&& rm -rf /tmp/*
Expand All @@ -14,9 +14,9 @@ COPY nativ[e]/generated /home/app/
COPY *.args /home/app/graalvm-native-image.args
RUN native-image @/home/app/graalvm-native-image.args -H:Class=io.micronaut.function.aws.runtime.MicronautLambdaRuntime -H:Name=application -cp "/home/app/libs/*:/home/app/classes/"

FROM amazonlinux:2023
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal
WORKDIR /function
RUN yum update -y && yum install -y zip && yum clean all
RUN dnf update -y && dnf install -y zip && dnf clean all
COPY --from=graalvm /home/app/application /function/func
RUN echo "#!/bin/sh" >> bootstrap && echo "set -euo pipefail" >> bootstrap && echo "./func -XX:MaximumHeapSizePercent=80 -Dio.netty.allocator.numDirectArenas=0 -Dio.netty.noPreferDirect=true -Djava.library.path=$(pwd)" >> bootstrap
RUN chmod 777 bootstrap
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM amazonlinux:2023 AS graalvm
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal AS graalvm
ENV LANG=en_US.UTF-8
RUN yum update -y && yum install -y gcc gcc-c++ glibc-devel curl-minimal bash zlib zlib-devel zlib-static zip tar gzip && yum clean all && rm -rf /var/cache/yum
RUN curl -4 -L https://download.oracle.com/graalvm/17/latest/graalvm-jdk-17_linux-aarch64_bin.tar.gz -o /tmp/graalvm.tar.gz \
RUN dnf update -y && dnf install -y gcc glibc-devel zlib-devel libstdc++-static tar && dnf clean all && rm -rf /var/cache/dnf
RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz -o /tmp/graalvm.tar.gz \
&& mkdir -p /usr/lib/graalvm \
&& tar -zxf /tmp/graalvm.tar.gz -C /usr/lib/graalvm --strip-components 1 \
&& rm -rf /tmp/*
Expand All @@ -14,9 +14,9 @@ COPY nativ[e]/generated /home/app/
COPY *.args /home/app/graalvm-native-image.args
RUN native-image @/home/app/graalvm-native-image.args -H:Class=io.micronaut.function.aws.runtime.MicronautLambdaRuntime -H:Name=application -cp "/home/app/libs/*:/home/app/classes/"

FROM amazonlinux:2023
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal
WORKDIR /function
RUN yum update -y && yum install -y zip && yum clean all
RUN dnf update -y && dnf install -y zip && dnf clean all
COPY --from=graalvm /home/app/application /function/func
RUN echo "#!/bin/sh" >> bootstrap && echo "set -euo pipefail" >> bootstrap && echo "./func -XX:MaximumHeapSizePercent=80 -Dio.netty.allocator.numDirectArenas=0 -Dio.netty.noPreferDirect=true -Djava.library.path=$(pwd)" >> bootstrap
RUN chmod 777 bootstrap
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
File dockerfile = new File("$basedir/target", "Dockerfile")
File expectedDockerfile = new File(basedir, "Dockerfile.${graalVmArch()}")
String expectedDockerfileText = expectedDockerfile.text.replace("17", "${System.getProperty("java.specification.version")}")

assert dockerfile.text == expectedDockerfileText

static String graalVmArch() {
String osArch = System.getProperty("os.arch")
if ("aarch64".equals(osArch)) {
Expand All @@ -13,6 +7,11 @@ static String graalVmArch() {
}
}

File dockerfile = new File("$basedir/target", "Dockerfile")
File expectedDockerfile = new File(basedir, "Dockerfile.${System.getProperty("java.specification.version")}.${graalVmArch()}")

assert dockerfile.text == expectedDockerfile.text

File log = new File(basedir, 'build.log')
assert log.exists()
assert log.text.contains("Copying /function/function.zip")
6 changes: 6 additions & 0 deletions micronaut-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@
<version>5.12.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit-pioneer</groupId>
<artifactId>junit-pioneer</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>

<!-- Micronaut -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public abstract class AbstractDockerMojo extends AbstractMicronautMojo {
public static final String X86_64_ARCH = "x64";
public static final String DEFAULT_ORACLE_LINUX_VERSION = "ol9";
public static final String ORACLE_CLOUD_FUNCTION_DEFAULT_CMD = "CMD [\"io.micronaut.oraclecloud.function.http.HttpFunction::handleRequest\"]";
public static final String GRAALVM_DOWNLOAD_URL = "https://download.oracle.com/graalvm/%s/%s/graalvm-jdk-%s_linux-%s_bin.tar.gz";

//Latest version of GraalVM for JDK 17 available under the GraalVM Free Terms and Conditions (GFTC) licence
public static final String GRAALVM_FOR_JDK17 = "17.0.12";

protected final MavenProject mavenProject;
protected final JibConfigurationService jibConfigurationService;
Expand Down Expand Up @@ -155,8 +159,12 @@ protected String graalVmVersion() {
/**
* @return the JVM version to use for GraalVM.
*/
protected String graalVmJvmVersion() {
return javaVersion().getMajorVersion() == 17 ? "17" : "21";
protected String graalVmDownloadUrl() {
if (javaVersion().getMajorVersion() == 17) {
return GRAALVM_DOWNLOAD_URL.formatted(17, "archive", GRAALVM_FOR_JDK17, graalVmArch());
} else {
return GRAALVM_DOWNLOAD_URL.formatted(21, "latest", 21, graalVmArch());
}
}

/**
Expand All @@ -171,9 +179,9 @@ protected String graalVmArch() {
*/
protected String getFrom() {
if (Boolean.TRUE.equals(staticNativeImage)) {
return getFromImage().orElse("ghcr.io/graalvm/native-image-community:" + graalVmJvmVersion() + "-muslib-" + oracleLinuxVersion);
return getFromImage().orElse("ghcr.io/graalvm/native-image-community:" + graalVmDownloadUrl() + "-muslib-" + oracleLinuxVersion);
} else {
return getFromImage().orElse("ghcr.io/graalvm/native-image-community:" + graalVmJvmVersion() + "-" + oracleLinuxVersion);
return getFromImage().orElse("ghcr.io/graalvm/native-image-community:" + graalVmDownloadUrl() + "-" + oracleLinuxVersion);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,24 +148,18 @@ private void checkJavaVersion(int maxAllowedVersion) throws MojoExecutionExcepti
private void buildDockerNativeLambda() throws IOException {
var buildImageCmdArguments = new HashMap<String, String>();

getLog().info("Using GRAALVM_JVM_VERSION: " + graalVmJvmVersion());
getLog().info("Using GRAALVM_ARCH: " + graalVmArch());

// Starter sets the right class in pom.xml:
// - For applications: io.micronaut.function.aws.runtime.MicronautLambdaRuntime
// - For function apps: com.example.BookLambdaRuntime
getLog().info("Using CLASS_NAME: " + mainClass);
BuildImageCmd buildImageCmd = addNativeImageBuildArgs(buildImageCmdArguments, () -> {
try {
return dockerService.buildImageCmd(DockerfileMojo.DOCKERFILE_AWS_CUSTOM_RUNTIME)
.withBuildArg("GRAALVM_VERSION", graalVmVersion())
.withBuildArg("GRAALVM_JVM_VERSION", graalVmJvmVersion())
.withBuildArg("GRAALVM_ARCH", graalVmArch());
.withBuildArg("GRAALVM_DOWNLOAD_URL", graalVmDownloadUrl());
} catch (IOException e) {
throw new DockerClientException(e.getMessage(), e);
}
});
buildImageCmd.withBuildArg("CLASS_NAME", mainClass);
buildImageCmd.withBuildArg("CLASS_NAME", mainClass).withNoCache(true);
String imageId = dockerService.buildImage(buildImageCmd);
File functionZip = dockerService.copyFromContainer(imageId, "/function/function.zip");
getLog().info("AWS Lambda Custom Runtime ZIP: " + functionZip.getPath());
Expand Down Expand Up @@ -204,7 +198,6 @@ private void buildDockerfile(String dockerfileName, boolean passClassName) throw

var buildImageCmdArguments = new HashMap<String, String>();

getLog().info("Using BASE_IMAGE: " + from);
if (StringUtils.isNotEmpty(baseImageRun) && Boolean.FALSE.equals(staticNativeImage)) {
buildImageCmdArguments.put("BASE_IMAGE_RUN", baseImageRun);
}
Expand All @@ -214,6 +207,7 @@ private void buildDockerfile(String dockerfileName, boolean passClassName) throw
}

BuildImageCmd buildImageCmd = addNativeImageBuildArgs(buildImageCmdArguments, () -> dockerService.buildImageCmd()
.withNoCache(true)
.withDockerfile(dockerfile)
.withTags(getTags())
.withBuildArg("BASE_IMAGE", from)
Expand All @@ -235,10 +229,7 @@ private BuildImageCmd addNativeImageBuildArgs(Map<String, String> buildImageCmdA
BuildImageCmd buildImageCmd = buildImageCmdSupplier.get();

for (Map.Entry<String, String> buildArg : buildImageCmdArguments.entrySet()) {
String key = buildArg.getKey();
String value = buildArg.getValue();
getLog().info("Using " + key + ": " + value);
buildImageCmd.withBuildArg(key, value);
buildImageCmd.withBuildArg(buildArg.getKey(), buildArg.getValue());
}

getNetworkMode().ifPresent(buildImageCmd::withNetworkMode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import io.micronaut.maven.jib.JibConfigurationService;
import io.micronaut.maven.jib.JibMicronautExtension;
import io.micronaut.maven.services.ApplicationConfigurationService;
import io.micronaut.maven.services.CompilerService;
import io.micronaut.maven.services.DockerService;
import io.micronaut.maven.services.ExecutorService;
import org.apache.maven.execution.MavenSession;
Expand Down Expand Up @@ -74,15 +73,13 @@ public class DockerfileMojo extends AbstractDockerMojo {
public static final String NATIVE_BUILD_TOOLS_MAVEN_PLUGIN = "org.graalvm.buildtools:native-maven-plugin";

private final ExecutorService executorService;
private final CompilerService compilerService;

@Inject
public DockerfileMojo(MavenProject mavenProject, DockerService dockerService, JibConfigurationService jibConfigurationService,
ApplicationConfigurationService applicationConfigurationService, ExecutorService executorService,
MavenSession mavenSession, MojoExecution mojoExecution, CompilerService compilerService) {
MavenSession mavenSession, MojoExecution mojoExecution) {
super(mavenProject, jibConfigurationService, applicationConfigurationService, dockerService, mavenSession, mojoExecution);
this.executorService = executorService;
this.compilerService = compilerService;
}

@Override
Expand Down Expand Up @@ -190,7 +187,6 @@ private void processDockerfile(File dockerfile) throws IOException {
if (dockerfile != null) {
var allLines = Files.readAllLines(dockerfile.toPath());
var result = new ArrayList<String>();

for (String line : allLines) {
if (!line.startsWith("ARG")) {
if (line.contains("BASE_IMAGE_RUN")) {
Expand All @@ -199,12 +195,10 @@ private void processDockerfile(File dockerfile) throws IOException {
result.add(line.replace("${BASE_IMAGE}", getFrom()));
} else if (line.contains("BASE_JAVA_IMAGE")) {
result.add(line.replace("${BASE_JAVA_IMAGE}", getBaseImage()));
} else if (line.contains("GRAALVM_") || line.contains("CLASS_NAME")) {
result.add(line
.replace("${GRAALVM_JVM_VERSION}", graalVmJvmVersion())
.replace("${GRAALVM_ARCH}", graalVmArch())
.replace("${CLASS_NAME}", mainClass)
);
} else if (line.contains("GRAALVM_DOWNLOAD_URL")) {
result.add(line.replace("${GRAALVM_DOWNLOAD_URL}", graalVmDownloadUrl()));
} else if (line.contains("CLASS_NAME")) {
result.add(line.replace("${CLASS_NAME}", mainClass));
} else if (line.contains("PORT")) {
result.add(line.replace("${PORT}", getPort()));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ public BuildImageCmd buildImageCmd() {
*/
public String buildImage(BuildImageCmd builder) {
verifyDockerRunning();
builder.getBuildArgs().forEach((k, v) -> LOG.info("Using {}: {}", k, v));
BuildImageResultCallback resultCallback = new BuildImageResultCallback() {
@Override
public void onNext(BuildResponseItem item) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
FROM amazonlinux:2023 AS graalvm
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal AS graalvm
ENV LANG=en_US.UTF-8
ARG GRAALVM_JVM_VERSION
ARG GRAALVM_ARCH
RUN yum update -y && yum install -y gcc gcc-c++ glibc-devel curl-minimal bash zlib zlib-devel zlib-static zip tar gzip && yum clean all && rm -rf /var/cache/yum
RUN curl -4 -L https://download.oracle.com/graalvm/${GRAALVM_JVM_VERSION}/latest/graalvm-jdk-${GRAALVM_JVM_VERSION}_linux-${GRAALVM_ARCH}_bin.tar.gz -o /tmp/graalvm.tar.gz \
RUN dnf update -y && dnf install -y gcc glibc-devel zlib-devel libstdc++-static tar && dnf clean all && rm -rf /var/cache/dnf
ARG GRAALVM_DOWNLOAD_URL
RUN curl -4 -L ${GRAALVM_DOWNLOAD_URL} -o /tmp/graalvm.tar.gz \
&& mkdir -p /usr/lib/graalvm \
&& tar -zxf /tmp/graalvm.tar.gz -C /usr/lib/graalvm --strip-components 1 \
&& rm -rf /tmp/*
Expand All @@ -17,9 +16,9 @@ COPY *.args /home/app/graalvm-native-image.args
ARG CLASS_NAME
RUN native-image @/home/app/graalvm-native-image.args -H:Class=${CLASS_NAME} -H:Name=application -cp "/home/app/libs/*:/home/app/classes/"

FROM amazonlinux:2023
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal
WORKDIR /function
RUN yum update -y && yum install -y zip && yum clean all
RUN dnf update -y && dnf install -y zip && dnf clean all
COPY --from=graalvm /home/app/application /function/func
RUN echo "#!/bin/sh" >> bootstrap && echo "set -euo pipefail" >> bootstrap && echo "./func -XX:MaximumHeapSizePercent=80 -Dio.netty.allocator.numDirectArenas=0 -Dio.netty.noPreferDirect=true -Djava.library.path=$(pwd)" >> bootstrap
RUN chmod 777 bootstrap
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.micronaut.maven;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junitpioneer.jupiter.RestoreSystemProperties;
import org.junitpioneer.jupiter.SetSystemProperty;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Properties;

import static io.micronaut.maven.AbstractDockerMojo.X86_64_ARCH;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RestoreSystemProperties
class DockerNativeMojoTest {

@ParameterizedTest
@CsvSource({
"17,https://download.oracle.com/graalvm/17/archive/graalvm-jdk-17.0.12_linux-x64_bin.tar.gz",
"21,https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz"
})
@SetSystemProperty(key = "os.arch", value = X86_64_ARCH)
void testGraalVmDownloadUrl(String javaVersion, String expectedUrl) throws URISyntaxException, IOException, InterruptedException {
var project = mock(MavenProject.class);
var session = mock(MavenSession.class);
var execution = mock(MojoExecution.class);
var properties = new Properties(1);
properties.put("maven.compiler.target", javaVersion);

when(session.getCurrentProject()).thenReturn(project);
when(session.getUserProperties()).thenReturn(new Properties());
when(session.getSystemProperties()).thenReturn(new Properties());
when(project.getProperties()).thenReturn(properties);

var mojo = new DockerNativeMojo(project, null, null, null, session, execution);

var actualUrl = mojo.graalVmDownloadUrl();

assertEquals(expectedUrl, actualUrl);

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(new URI(actualUrl))
.method("HEAD", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.discarding());

assertEquals(200, response.statusCode());
}
}
Loading