Skip to content

Commit

Permalink
Merge pull request #727 from xlight05/add-builer-image
Browse files Browse the repository at this point in the history
Add graalvm builder image configurations
  • Loading branch information
xlight05 authored Jul 31, 2023
2 parents c8c831d + 03f1b39 commit 156633b
Show file tree
Hide file tree
Showing 20 changed files with 252 additions and 47 deletions.
2 changes: 1 addition & 1 deletion ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "cloud"
version = "2.9.0"
version = "2.9.1"
repository = "https://github.com/ballerina-platform/module-ballerina-c2c"
license = ["Apache-2.0"]
keywords = ["cloud", "kubernetes", "docker", "k8s", "c2c"]
Expand Down
2 changes: 1 addition & 1 deletion ballerina/CompilerPlugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ id = "code2cloud"
class = "io.ballerina.c2c.C2CCompilerPlugin"

[[dependency]]
path = "../compiler-plugin/build/libs/cloud-compiler-plugin-2.9.0.jar"
path = "../compiler-plugin/build/libs/cloud-compiler-plugin-2.9.1-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ distribution-version = "2201.7.0"
[[package]]
org = "ballerina"
name = "cloud"
version = "2.9.0"
version = "2.9.1"
modules = [
{org = "ballerina", packageName = "cloud", moduleName = "cloud"}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 io.ballerina.c2c.test.samples;

import io.ballerina.c2c.exceptions.KubernetesPluginException;
import io.ballerina.c2c.test.utils.KubernetesTestUtils;
import io.ballerina.c2c.utils.KubernetesUtils;
import org.apache.commons.io.FilenameUtils;
import org.testng.Assert;
import org.testng.annotations.Test;

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.nio.file.Paths;

import static io.ballerina.c2c.KubernetesConstants.DOCKER;

/**
* Test cases for docker cloud option as a project.
*/
public class NativeBuilderConfigTest {

protected static final Path SAMPLE_DIR = Paths.get(FilenameUtils.separatorsToSystem(
System.getProperty("sampleDir")));
private static final Path SOURCE_DIR_PATH = SAMPLE_DIR.resolve("graalvm-custom-builder");
private static final Path DOCKER_TARGET_PATH =
SOURCE_DIR_PATH.resolve("target").resolve(DOCKER).resolve("custom_builder");
@Test
public void validateDockerBuildOption() throws IOException, InterruptedException, KubernetesPluginException {
Assert.assertEquals(KubernetesTestUtils.compileBallerinaProject(SOURCE_DIR_PATH), 0);
File dockerFile = DOCKER_TARGET_PATH.resolve("Dockerfile").toFile();
String content = Files.readString(dockerFile.toPath(), StandardCharsets.UTF_8);
Assert.assertTrue(dockerFile.exists());
Assert.assertTrue(content.contains("RUN sh build-native.sh custom_builder.jar custom_builder " +
"'--static --libc=musl'"));
Assert.assertTrue(content.contains("FROM ballerina/musl-native-builder:2201.7.x as build"));
Assert.assertTrue(content.contains("FROM debian:11-slim"));
KubernetesUtils.deleteDirectory(DOCKER_TARGET_PATH);
}

@Test(dependsOnMethods = { "validateDockerBuildOption" })
public void validateK8sBuildOption() throws IOException, InterruptedException, KubernetesPluginException {
Assert.assertEquals(KubernetesTestUtils.compileBallerinaProject(SOURCE_DIR_PATH, "k8s"), 0);
File dockerFile = DOCKER_TARGET_PATH.resolve("Dockerfile").toFile();
String content = Files.readString(dockerFile.toPath(), StandardCharsets.UTF_8);
Assert.assertTrue(dockerFile.exists());
Assert.assertTrue(content.contains("RUN sh build-native.sh custom_builder.jar custom_builder " +
"'--static --libc=musl'"));
Assert.assertTrue(content.contains("FROM ballerina/musl-native-builder:2201.7.x as build"));
Assert.assertTrue(content.contains("FROM debian:11-slim"));
KubernetesUtils.deleteDirectory(DOCKER_TARGET_PATH);
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
{
"expected": {
"result": {
"edit": {
"documentChanges": [
{
"options": {
"overwrite": false,
"ignoreIfExists": true
},
"kind": "create"
},
{
"edits": [
{
"range": {
"start": {
"line": 0,
"character": 0
},
"end": {
"line": 0,
"character": 0
}
},
"newText":"# This file contains most used configurations supported by Ballerina Code to Cloud\n# All the fields are optional. If these fields are not specified, default value will be taken from the compiler.\n# Full Code to Cloud specification can be accessed from https://github.com/ballerina-platform/ballerina-spec/blob/master/c2c/code-to-cloud-spec.md\n# Uncomment Any field below if you want to override the default value.\n\n# Settings related to artifacts generation\n#[settings]\n#buildImage = true # Build the Docker image while building the project\n#thinJar = true # Use the thin jars in the container\n#\n# Properties related to the container image\n#[container.image]\n#name = \"hello\" # Name of the container image\n#repository = \"ballerina\" # Container repository to host the container\n#tag = \"latest\" # Tag of the container\n#base = \"ballerina/jvm-runtime:1.0\" # Base container of the container image\n#\n# Copy the files to the container image\n#[[container.copy.files]]\n#sourceFile = \"./data/data.txt\" # Path to the external file\n#target = \"/home/ballerina/data/data.txt\" # Path of the file within the container\n#\n# External files required for the code\n#[[cloud.config.maps]]\n#file = \"resource/file.text\" # Path of the external file\n#mount_path = \"/home/ballerina/foo/file.conf\" # Path of the file in the container\n#\n# Environment variables required for the application\n#[[cloud.config.envs]]\n#key_ref = \"FOO\" # Key of the environment variable\n#name = \"foo\" # Name of the env if it is different from the key\n#config_name = \"module-foo\" # Name of the config config map\n#\n# Properties related to the deployment\n#[cloud.deployment]\n#min_memory = \"100Mi\" # Minimum memory allocated to the container\n#max_memory = \"512Mi\" # Maximum memory allocated to the container\n#min_cpu = \"200m\" # Minimum CPU allocated to the container\n#max_cpu = \"500m\" # Maximum CPU allocated to the container\n#\n# Matrices to auto-scale the container\n#[cloud.deployment.autoscaling]\n#min_replicas = 1 # Minimum number of replicas of the container alive at a given time\n#max_replicas = 2 # Maximum number of replicas of the container alive at a given time\n#cpu = 50 # CPU Utilization threshold for spawning a new instance\n#\n# Probe to indicate whether the container is ready to respond to requests. No readiness probe will be generated if not specified\n#[cloud.deployment.probes.readiness]\n#port = 9091 # Port of the readiness probe endpoint\n#path = \"/probes/readyz\" # Endpoint of the readiness probe\n#\n# Probe to indicate whether the container is running. No liveness probe will be generated if not specified\n#[cloud.deployment.probes.liveness]\n#port = 9091 # Port of the liveness probe endpoint\n#path = \"/probes/healthz\" # Endpoint of the liveness probe\n#\n# Volume definitions of the application. No default volumes will be generated if not specified\n#[[cloud.deployment.storage.volumes]]\n#name = \"volume1\" # Name of the volume\n#local_path = \"files\" # Path of the volume\n#size = \"2Gi\" # Maximum size of the volume\n#"
}
]
}
]
}
},
"jsonrpc": "2.0"
}
"expected": {
"result": {
"edit": {
"documentChanges": [
{
"options": {
"overwrite": false,
"ignoreIfExists": true
},
"kind": "create"
},
{
"edits": [
{
"range": {
"start": {
"line": 0,
"character": 0
},
"end": {
"line": 0,
"character": 0
}
},
"newText": "# This file contains most used configurations supported by Ballerina Code to Cloud\n# All the fields are optional. If these fields are not specified, default value will be taken from the compiler.\n# Full Code to Cloud specification can be accessed from https://github.com/ballerina-platform/ballerina-spec/blob/master/c2c/code-to-cloud-spec.md\n# Uncomment Any field below if you want to override the default value.\n\n# Settings related to artifacts generation\n#[settings]\n#buildImage = true # Build the Docker image while building the project\n#thinJar = true # Use the thin jars in the container\n#\n# Properties related to the container image\n#[container.image]\n#name = \"hello\" # Name of the container image\n#repository = \"ballerina\" # Container repository to host the container\n#tag = \"latest\" # Tag of the container\n#base = \"ballerina/jvm-runtime:1.0\" # Base container of the container image\n#\n# Copy the files to the container image\n#[[container.copy.files]]\n#sourceFile = \"./data/data.txt\" # Path to the external file\n#target = \"/home/ballerina/data/data.txt\" # Path of the file within the container\n#\n# External files required for the code\n#[[cloud.config.maps]]\n#file = \"resource/file.text\" # Path of the external file\n#mount_path = \"/home/ballerina/foo/file.conf\" # Path of the file in the container\n#\n# Environment variables required for the application\n#[[cloud.config.envs]]\n#key_ref = \"FOO\" # Key of the environment variable\n#name = \"foo\" # Name of the env if it is different from the key\n#config_name = \"module-foo\" # Name of the config config map\n#\n# Properties related to the deployment\n#[cloud.deployment]\n#min_memory = \"100Mi\" # Minimum memory allocated to the container\n#max_memory = \"512Mi\" # Maximum memory allocated to the container\n#min_cpu = \"200m\" # Minimum CPU allocated to the container\n#max_cpu = \"500m\" # Maximum CPU allocated to the container\n#\n# Matrices to auto-scale the container\n#[cloud.deployment.autoscaling]\n#min_replicas = 1 # Minimum number of replicas of the container alive at a given time\n#max_replicas = 2 # Maximum number of replicas of the container alive at a given time\n#cpu = 50 # CPU Utilization threshold for spawning a new instance\n#\n# Probe to indicate whether the container is ready to respond to requests. No readiness probe will be generated if not specified\n#[cloud.deployment.probes.readiness]\n#port = 9091 # Port of the readiness probe endpoint\n#path = \"/probes/readyz\" # Endpoint of the readiness probe\n#\n# Probe to indicate whether the container is running. No liveness probe will be generated if not specified\n#[cloud.deployment.probes.liveness]\n#port = 9091 # Port of the liveness probe endpoint\n#path = \"/probes/healthz\" # Endpoint of the liveness probe\n#\n# Volume definitions of the application. No default volumes will be generated if not specified\n#[[cloud.deployment.storage.volumes]]\n#name = \"volume1\" # Name of the volume\n#local_path = \"files\" # Path of the volume\n#size = \"2Gi\" # Maximum size of the volume\n#\n# Properties related to the builder image of the multistage build\n#[graalvm.builder]\n#base = \"ballerina/native-builder:latest\" # base image of the builder image\n#buildCmd = \"native-image -jar hello.jar hello\" # RUN statement to build the native image\n#"
}
]
}
]
}
},
"jsonrpc": "2.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@
"sortText": "C",
"insertText": "[[cloud.deployment.storage.volumes]]"
},
{
"label": "graalvm.builder",
"kind": "Snippet",
"detail": "Table",
"sortText": "C",
"insertText": "[graalvm.builder]"
},
{
"label": "cmd",
"kind": "Snippet",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@
"detail": "Table Array",
"sortText": "C",
"insertText": "[[cloud.secret.files]]"
},
{
"label": "graalvm.builder",
"kind": "Snippet",
"detail": "Table",
"sortText": "C",
"insertText": "[graalvm.builder]"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@
"detail": "Table Array",
"sortText": "C",
"insertText": "[[cloud.secret.files]]"
},
{
"label": "graalvm.builder",
"kind": "Snippet",
"detail": "Table",
"sortText": "C",
"insertText": "[graalvm.builder]"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@
"detail": "Table Array",
"sortText": "C",
"insertText": "[[cloud.secret.files]]"
},
{
"label": "graalvm.builder",
"kind": "Snippet",
"detail": "Table",
"sortText": "C",
"insertText": "[graalvm.builder]"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@
"detail": "Table Array",
"sortText": "C",
"insertText": "[[cloud.secret.files]]"
},
{
"label": "graalvm.builder",
"kind": "Snippet",
"detail": "Table",
"sortText": "C",
"insertText": "[graalvm.builder]"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<class name="io.ballerina.c2c.test.samples.NativeTest"/>
<class name="io.ballerina.c2c.test.samples.NativeArgsTest"/>
<class name="io.ballerina.c2c.test.samples.NativeBaseTest"/>
<class name="io.ballerina.c2c.test.samples.NativeBuilderConfigTest"/>
<class name="io.ballerina.c2c.test.samples.DockerProjectTest"/>
<class name="io.ballerina.c2c.test.samples.DockerSingleTest"/>
<class name="io.ballerina.c2c.test.SettingsMultiYAMLTest"/>
Expand Down
1 change: 1 addition & 0 deletions compiler-plugin-tests/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<class name="io.ballerina.c2c.test.samples.NativeTest"/>
<class name="io.ballerina.c2c.test.samples.NativeArgsTest"/>
<class name="io.ballerina.c2c.test.samples.NativeBaseTest"/>
<class name="io.ballerina.c2c.test.samples.NativeBuilderConfigTest"/>
<class name="io.ballerina.c2c.test.samples.DockerProjectTest"/>
<class name="io.ballerina.c2c.test.samples.DockerSingleTest"/>
<class name="io.ballerina.c2c.test.SettingsMultiYAMLTest"/>
Expand Down
5 changes: 5 additions & 0 deletions compiler-plugin/spotbugs-exclude.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
<Class name="io.ballerina.c2c.tasks.C2CCodeGeneratedTask"/>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
</Match>
<Match>
<Class name="io.ballerina.c2c.utils.KubernetesUtils"/>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
</Match>

<Match>
<Class name="io.ballerina.c2c.utils.NativeDockerGenerator"/>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public class DockerModel {
private Path fatJarPath;
private boolean thinJar = true;
private String graalvmBuildArgs;
private boolean isGraalVMBuild = false;
private String builderBase;
private String builderCmd;

public DockerModel() {
// Initialize with default values except for image name
Expand All @@ -70,10 +73,12 @@ public DockerModel() {
DockerGenConstants.OPENJDK_11_JRE_SLIM_BASE;
this.enableDebug = false;
this.debugPort = 5005;
externalFiles = new HashSet<>();
commandArg = "";
env = new HashMap<>();
dependencyJarPaths = new TreeSet<>();
this.externalFiles = new HashSet<>();
this.commandArg = "";
this.env = new HashMap<>();
this.dependencyJarPaths = new TreeSet<>();
this.builderBase = DockerGenConstants.NATIVE_BUILDER_IMAGE;
this.builderCmd = "";
}

public void addDependencyJarPaths(Set<Path> paths) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,19 @@ public static void resolveDockerToml(KubernetesModel model) throws KubernetesPlu
copyFiles.add(copyFileModel);
}
dockerModel.setThinJar(isThinJar(toml, dockerModel));
dockerModel.setBuilderBase(TomlHelper.getString(toml, "graalvm.builder.base",
DockerGenConstants.NATIVE_BUILDER_IMAGE));

String fatJarFileName = dockerModel.getFatJarPath().getFileName().toString();
String executableName = fatJarFileName.replaceFirst(".jar", "");
StringBuilder defaultBuilderCmd = new StringBuilder().append("sh build-native.sh ").
append(fatJarFileName).append(" ").append(executableName);
if (!dockerModel.getGraalvmBuildArgs().equals("")) {
defaultBuilderCmd.append(" '").append(dockerModel.getGraalvmBuildArgs()).append("'");
}

dockerModel.setBuilderCmd(TomlHelper.getString(toml, "graalvm.builder.buildCmd",
defaultBuilderCmd.toString()));
try {
dockerModel.setCopyFiles(copyFiles);
} catch (DockerGenException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,13 @@ private String generateMultiStageDockerfile() {

String fatJarFileName = this.dockerModel.getFatJarPath().getFileName().toString();
String executableName = fatJarFileName.replaceFirst(".jar", "");
StringBuilder nativeBuildScriptExec = new StringBuilder().append("RUN sh build-native.sh ").
append(fatJarFileName).append(" ").append(executableName);
if (!this.dockerModel.getGraalvmBuildArgs().equals("")) {
nativeBuildScriptExec.append(" '").append(this.dockerModel.getGraalvmBuildArgs()).append("'");
}
StringBuilder dockerfileContent =
new StringBuilder().append("# Auto Generated Dockerfile").append(LINE_SEPARATOR).append("FROM ")
.append(DockerGenConstants.NATIVE_BUILDER_IMAGE).append(" as build").append(LINE_SEPARATOR)
.append(dockerModel.getBuilderBase()).append(" as build").append(LINE_SEPARATOR)
.append(LINE_SEPARATOR).append("WORKDIR /app/build").append(LINE_SEPARATOR)
.append(LINE_SEPARATOR).append("COPY ").append(fatJarFileName).append(" .")
.append(LINE_SEPARATOR).append(LINE_SEPARATOR)
.append(nativeBuildScriptExec)
.append("RUN ").append(this.dockerModel.getBuilderCmd())
.append(LINE_SEPARATOR).append(LINE_SEPARATOR).append("FROM ")
.append(dockerModel.getBaseImage()).append(LINE_SEPARATOR)
.append(LINE_SEPARATOR);
Expand Down
Loading

0 comments on commit 156633b

Please sign in to comment.