From 04ba58e50a8fd091f34024a929e01b8a8c9915bb Mon Sep 17 00:00:00 2001 From: xlight05 Date: Fri, 5 Apr 2024 13:58:51 +0530 Subject: [PATCH] Fix GraalVM default base image --- .../c2c/test/samples/NativeJobTest.java | 99 +++++++++++++++++++ .../src/test/resources/testng-integration.xml | 1 + .../src/test/resources/testng.xml | 1 + .../ballerina/c2c/models/DeploymentModel.java | 3 - .../ballerina/c2c/utils/KubernetesUtils.java | 9 +- examples/kubernetes-native-job/Ballerina.toml | 9 ++ examples/kubernetes-native-job/README.md | 52 ++++++++++ .../kubernetes-native-job/hello_world_job.bal | 7 ++ 8 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 compiler-plugin-tests/src/test/java/io/ballerina/c2c/test/samples/NativeJobTest.java create mode 100644 examples/kubernetes-native-job/Ballerina.toml create mode 100644 examples/kubernetes-native-job/README.md create mode 100644 examples/kubernetes-native-job/hello_world_job.bal diff --git a/compiler-plugin-tests/src/test/java/io/ballerina/c2c/test/samples/NativeJobTest.java b/compiler-plugin-tests/src/test/java/io/ballerina/c2c/test/samples/NativeJobTest.java new file mode 100644 index 00000000..f2725962 --- /dev/null +++ b/compiler-plugin-tests/src/test/java/io/ballerina/c2c/test/samples/NativeJobTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024, 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.q + * 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 com.github.dockerjava.api.command.InspectImageResponse; +import io.ballerina.c2c.KubernetesConstants; +import io.ballerina.c2c.exceptions.KubernetesPluginException; +import io.ballerina.c2c.test.utils.KubernetesTestUtils; +import io.ballerina.c2c.utils.KubernetesUtils; +import io.fabric8.kubernetes.api.model.Container; +import io.fabric8.kubernetes.api.model.batch.v1.Job; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +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.util.List; + +import static io.ballerina.c2c.KubernetesConstants.DOCKER; +import static io.ballerina.c2c.KubernetesConstants.KUBERNETES; +import static io.ballerina.c2c.test.utils.KubernetesTestUtils.getDockerImage; + +/** + * Test cases for sample 4. + */ +public class NativeJobTest extends SampleTest { + + private static final Path SOURCE_DIR_PATH = SAMPLE_DIR.resolve("kubernetes-native-job"); + private static final Path DOCKER_TARGET_PATH = SOURCE_DIR_PATH.resolve("target").resolve(DOCKER) + .resolve("hello"); + private static final Path KUBERNETES_TARGET_PATH = SOURCE_DIR_PATH.resolve("target").resolve(KUBERNETES) + .resolve("hello"); + private static final String DOCKER_IMAGE = "xlight-hello-0.0.1:latest"; + + @BeforeClass + public void compileSample() throws IOException, InterruptedException { + + Assert.assertEquals(KubernetesTestUtils.compileBallerinaProject(SOURCE_DIR_PATH), 0); + File dockerFile = DOCKER_TARGET_PATH.resolve("Dockerfile").toFile(); + Assert.assertTrue(dockerFile.exists()); + InspectImageResponse imageInspect = getDockerImage(DOCKER_IMAGE); + Assert.assertNotNull(imageInspect.getConfig()); + } + + @Test + public void validateDockerfile() throws IOException { + + File dockerFile = DOCKER_TARGET_PATH.resolve("Dockerfile").toFile(); + Assert.assertTrue(dockerFile.exists()); + String content = Files.readString(dockerFile.toPath(), StandardCharsets.UTF_8); + Assert.assertTrue(content.contains("RUN native-image -jar hello.jar -H:Name=hello --no-fallback " + + "-H:+StaticExecutableWithDynamicLibC")); + Assert.assertTrue(content.contains("FROM ghcr.io/graalvm/native-image-community:17-ol8 as build")); + Assert.assertTrue(content.contains("FROM gcr.io/distroless/base")); + } + + @Test + public void validateJob() throws IOException { + + File jobYAML = KUBERNETES_TARGET_PATH.resolve("hello.yaml").toFile(); + Job job = KubernetesTestUtils.loadYaml(jobYAML); + Assert.assertEquals(job.getMetadata().getName(), "xlight-hello-0-job"); + List containers = job.getSpec().getTemplate().getSpec().getContainers(); + Assert.assertEquals(containers.size(), 1); + Container container = containers.get(0); + Assert.assertEquals(container.getImage(), DOCKER_IMAGE); + Assert.assertEquals(job.getSpec().getTemplate().getSpec() + .getRestartPolicy(), KubernetesConstants.RestartPolicy.OnFailure.name()); + } + + @AfterClass + public void cleanUp() throws KubernetesPluginException { + + KubernetesUtils.deleteDirectory(KUBERNETES_TARGET_PATH); + KubernetesUtils.deleteDirectory(DOCKER_TARGET_PATH); + KubernetesTestUtils.deleteDockerImage(DOCKER_IMAGE); + } +} diff --git a/compiler-plugin-tests/src/test/resources/testng-integration.xml b/compiler-plugin-tests/src/test/resources/testng-integration.xml index f8c9fff3..4983a934 100644 --- a/compiler-plugin-tests/src/test/resources/testng-integration.xml +++ b/compiler-plugin-tests/src/test/resources/testng-integration.xml @@ -42,6 +42,7 @@ + diff --git a/compiler-plugin-tests/src/test/resources/testng.xml b/compiler-plugin-tests/src/test/resources/testng.xml index 0cfcd102..b75b5f3d 100644 --- a/compiler-plugin-tests/src/test/resources/testng.xml +++ b/compiler-plugin-tests/src/test/resources/testng.xml @@ -47,6 +47,7 @@ + diff --git a/compiler-plugin/src/main/java/io/ballerina/c2c/models/DeploymentModel.java b/compiler-plugin/src/main/java/io/ballerina/c2c/models/DeploymentModel.java index ea70ad10..480c4a66 100644 --- a/compiler-plugin/src/main/java/io/ballerina/c2c/models/DeploymentModel.java +++ b/compiler-plugin/src/main/java/io/ballerina/c2c/models/DeploymentModel.java @@ -17,7 +17,6 @@ */ package io.ballerina.c2c.models; -import io.ballerina.c2c.DockerGenConstants; import io.fabric8.kubernetes.api.model.ContainerPort; import io.fabric8.kubernetes.api.model.Probe; import io.fabric8.kubernetes.api.model.Quantity; @@ -48,7 +47,6 @@ public class DeploymentModel extends KubernetesModel { private String namespace; private String image; private boolean buildImage; - private String baseImage; private String dockerHost; private String dockerCertPath; private List ports; @@ -70,7 +68,6 @@ public DeploymentModel() { this.replicas = 1; this.envVars = new ArrayList<>(); this.buildImage = true; - this.baseImage = DockerGenConstants.JRE_SLIM_BASE; this.labels = new LinkedHashMap<>(); this.nodeSelector = new LinkedHashMap<>(); this.ports = new ArrayList<>(); diff --git a/compiler-plugin/src/main/java/io/ballerina/c2c/utils/KubernetesUtils.java b/compiler-plugin/src/main/java/io/ballerina/c2c/utils/KubernetesUtils.java index 49a619c3..64cf72d6 100644 --- a/compiler-plugin/src/main/java/io/ballerina/c2c/utils/KubernetesUtils.java +++ b/compiler-plugin/src/main/java/io/ballerina/c2c/utils/KubernetesUtils.java @@ -286,14 +286,15 @@ public static void resolveDockerToml(KubernetesModel model) throws KubernetesPlu defaultBuilderCmd.append(" -H:+StaticExecutableWithDynamicLibC"); } dockerModel.setBuilderCmd(defaultBuilderCmd.toString()); + String defaultBaseImage = DockerGenConstants.JRE_SLIM_BASE; + if (dockerModel.isGraalVMBuild()) { + defaultBaseImage = DockerGenConstants.NATIVE_RUNTIME_BASE_IMAGE; + } + dockerModel.setBaseImage(defaultBaseImage); if (toml != null) { dockerModel .setRegistry(TomlHelper.getString(toml, containerImage + ".repository", null)); dockerModel.setTag(TomlHelper.getString(toml, containerImage + ".tag", dockerModel.getTag())); - String defaultBaseImage = DockerGenConstants.JRE_SLIM_BASE; - if (dockerModel.isGraalVMBuild()) { - defaultBaseImage = DockerGenConstants.NATIVE_RUNTIME_BASE_IMAGE; - } dockerModel.setBaseImage(TomlHelper.getString(toml, containerImage + ".base", defaultBaseImage)); dockerModel.setEntryPoint(TomlHelper.getString(toml, containerImage + ".entrypoint", dockerModel.getEntryPoint())); diff --git a/examples/kubernetes-native-job/Ballerina.toml b/examples/kubernetes-native-job/Ballerina.toml new file mode 100644 index 00000000..f150bcd2 --- /dev/null +++ b/examples/kubernetes-native-job/Ballerina.toml @@ -0,0 +1,9 @@ +[package] +org = "xlight" +name= "hello" +version = "0.0.1" + +[build-options] +observabilityIncluded = true +cloud = "k8s" +graalvm = true diff --git a/examples/kubernetes-native-job/README.md b/examples/kubernetes-native-job/README.md new file mode 100644 index 00000000..499717a6 --- /dev/null +++ b/examples/kubernetes-native-job/README.md @@ -0,0 +1,52 @@ +## Kubernetes Job + +- This sample shows how to run a ballerina application as a job using graalvm in Kubernetes. + +### How to write: +This segment shows how a c2c segment is mapped into cloud element. + +1. `Ballerina code` segment +```bal +@cloud:Task +public function main(string... args) { + io:println("hello world"); +} + +``` +2. Kubernetes YAML file segment +```yaml +apiVersion: "batch/v1" +kind: "Job" +metadata: + name: "anjana-main-tas-job" +spec: + template: + spec: + containers: + - image: "anjana-main_task-0.1.0:latest" + name: "anjana-main-tas-job" + restartPolicy: "OnFailure" + +``` + + +### How to run: + +1. Build the Ballerina file. +```bash +$> bal build --cloud=k8s hello_world_job.bal +Compiling source + hello_world_job.bal + +Generating executable + +Generating artifacts... + + @kubernetes:Job - complete 1/1 + @kubernetes:Docker - complete 2/2 + + Execute the below command to deploy the Kubernetes artifacts: + kubectl apply -f /Users/luheerathan/luhee/Ballerina-Project-Files/Test/c2c-test/examples/kubernetes-job/kubernetes + + hello_world_job.jar +``` diff --git a/examples/kubernetes-native-job/hello_world_job.bal b/examples/kubernetes-native-job/hello_world_job.bal new file mode 100644 index 00000000..8d838375 --- /dev/null +++ b/examples/kubernetes-native-job/hello_world_job.bal @@ -0,0 +1,7 @@ +import ballerina/io; +import ballerina/cloud; + +@cloud:Task +public function main(string... args) { + io:println("hello world"); +}