Skip to content

Commit

Permalink
feat (jkube-kit) : Add HelidonGenerator for generating opinionated co…
Browse files Browse the repository at this point in the history
…ntainer images for Helidon projects (eclipse-jkube#1714)

+ Add jkube-kit-helidon module which contains generator for creating
  opinionated ImageConfiguration for Helidon

Signed-off-by: Rohan Kumar <rohaan@redhat.com>
  • Loading branch information
rohanKanojia committed Apr 10, 2023
1 parent 77150f4 commit 684df4a
Show file tree
Hide file tree
Showing 19 changed files with 874 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Usage:
./scripts/extract-changelog-for-version.sh 1.3.37 5
```
### 1.13-SNAPSHOT
* Fix #1714: Add HelidonGenerator to add opinionated container image for Helidon applications

### 1.12.0 (2023-04-03)
* Fix #1179: Move storageClass related functionality out of VolumePermissionEnricher to PersistentVolumeClaimStorageClassEnricher
Expand Down
5 changes: 5 additions & 0 deletions gradle-plugin/kubernetes/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@
<artifactId>jkube-kit-smallrye</artifactId>
<version>${jkube.kit.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jkube</groupId>
<artifactId>jkube-kit-helidon</artifactId>
<version>${jkube.kit.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jkube</groupId>
<artifactId>jkube-kit-profiles</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
- karaf
- vertx
- micronaut
- helidon
- java-exec
- webapp
watcher:
Expand Down Expand Up @@ -120,6 +121,7 @@
- wildfly-jar
- karaf
- vertx
- helidon
- java-exec
- webapp
enricher:
Expand Down
54 changes: 54 additions & 0 deletions jkube-kit/jkube-kit-helidon/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jkube-kit-parent</artifactId>
<groupId>org.eclipse.jkube</groupId>
<version>1.13-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>

<artifactId>jkube-kit-helidon</artifactId>
<name>JKube Kit :: Helidon</name>

<dependencies>

<dependency>
<groupId>org.eclipse.jkube</groupId>
<artifactId>jkube-kit-enricher-specific</artifactId>
</dependency>

<dependency>
<groupId>org.eclipse.jkube</groupId>
<artifactId>jkube-kit-generator-java-exec</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.helidon;

import org.eclipse.jkube.kit.common.JavaProject;
import org.eclipse.jkube.kit.common.util.JKubeProjectUtil;

import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.function.Supplier;

import static org.eclipse.jkube.kit.common.util.JKubeProjectUtil.getClassLoader;
import static org.eclipse.jkube.kit.common.util.PropertiesUtil.getPropertiesFromResource;
import static org.eclipse.jkube.kit.common.util.PropertiesUtil.toMap;
import static org.eclipse.jkube.kit.common.util.YamlUtil.getPropertiesFromYamlResource;

public class HelidonUtils {
private static final String HELIDON_HTTP_PORT = "server.port";

private HelidonUtils() { }

public static boolean hasHelidonDependencies(JavaProject javaProject) {
return JKubeProjectUtil.hasTransitiveDependency(javaProject, "io.helidon.webserver", "helidon-webserver");
}

public static boolean hasHelidonGraalNativeImageExtension(JavaProject javaProject) {
return JKubeProjectUtil.hasDependency(javaProject, "io.helidon.integrations.graal", "helidon-graal-native-image-extension") ||
JKubeProjectUtil.hasDependency(javaProject, "io.helidon.integrations.graal", "helidon-mp-graal-native-image-extension");
}

public static Properties getHelidonConfiguration(JavaProject javaProject) {
final URLClassLoader urlClassLoader = getClassLoader(javaProject);
final List<Supplier<Properties>> sources = Arrays.asList(
() -> getPropertiesFromResource(urlClassLoader.findResource("META-INF/microprofile-config.properties")),
() -> getPropertiesFromYamlResource(urlClassLoader.findResource("application.yaml")),
() -> getPropertiesFromYamlResource(urlClassLoader.findResource("application.yml"))
);
for (Supplier<Properties> source : sources) {
final Properties props = source.get();
if (!props.isEmpty()) {
props.putAll(toMap(javaProject.getProperties()));
return props;
}
}
return javaProject.getProperties();
}

public static String extractPort(Properties properties, String defaultValue) {
return properties.getProperty(HELIDON_HTTP_PORT, defaultValue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.helidon.generator;

import org.eclipse.jkube.kit.common.Assembly;
import org.eclipse.jkube.kit.common.AssemblyConfiguration;
import org.eclipse.jkube.kit.common.AssemblyFileSet;
import org.eclipse.jkube.kit.common.JavaProject;
import org.eclipse.jkube.kit.common.util.JKubeProjectUtil;

import java.io.File;

import static org.eclipse.jkube.kit.common.util.FileUtil.getRelativePath;

public class HelidonAssemblies {
public static final HelidonAssembly NATIVE = helidonGenerator -> {
final JavaProject project = helidonGenerator.getContext().getProject();
final AssemblyFileSet.AssemblyFileSetBuilder artifactFileSetBuilder = AssemblyFileSet.builder()
.outputDirectory(new File("."))
.directory(getRelativePath(project.getBaseDirectory(), project.getBuildDirectory()))
.fileMode("0755");
File nativeBinary = new File(project.getBuildDirectory(), project.getBuildFinalName());
if (nativeBinary.exists()) {
artifactFileSetBuilder.include(nativeBinary.getName());
}
return createAssemblyConfiguration(helidonGenerator.getBuildWorkdir())
.layer(Assembly.builder().fileSet(artifactFileSetBuilder.build()).build())
.build();
};

public static final HelidonAssembly STANDARD = helidonGenerator -> {
final JavaProject project = helidonGenerator.getContext().getProject();
AssemblyFileSet.AssemblyFileSetBuilder libFileSet = AssemblyFileSet.builder()
.outputDirectory(new File("."))
.directory(getRelativePath(project.getBaseDirectory(), project.getBuildDirectory()))
.include("libs")
.fileMode("0640");
AssemblyFileSet.AssemblyFileSetBuilder artifactFileSet = AssemblyFileSet.builder()
.outputDirectory(new File("."))
.directory(getRelativePath(project.getBaseDirectory(), project.getBuildDirectory()))
.fileMode("0640");
File defaultArtifactFile = JKubeProjectUtil.getFinalOutputArtifact(project);
if (defaultArtifactFile != null) {
artifactFileSet.include(getRelativePath(project.getBuildDirectory(), defaultArtifactFile).getPath());
}
return createAssemblyConfiguration(helidonGenerator.getBuildWorkdir())
.layer(Assembly.builder().id("libs").fileSet(libFileSet.build()).build())
.layer(Assembly.builder().id("artifact").fileSet(artifactFileSet.build()).build())
.build();
};

private static AssemblyConfiguration.AssemblyConfigurationBuilder createAssemblyConfiguration(String targetDir) {
return AssemblyConfiguration.builder()
.targetDir(targetDir)
.excludeFinalOutputArtifact(true);
}

@FunctionalInterface
public interface HelidonAssembly {
AssemblyConfiguration createAssemblyConfiguration(HelidonGenerator quarkusGenerator);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.helidon.generator;

import org.eclipse.jkube.generator.api.GeneratorContext;
import org.eclipse.jkube.generator.javaexec.JavaExecGenerator;
import org.eclipse.jkube.kit.common.Arguments;
import org.eclipse.jkube.kit.common.AssemblyConfiguration;
import org.eclipse.jkube.kit.config.image.ImageConfiguration;

import java.util.List;
import java.util.Optional;

import static org.eclipse.jkube.helidon.HelidonUtils.extractPort;
import static org.eclipse.jkube.helidon.HelidonUtils.getHelidonConfiguration;
import static org.eclipse.jkube.helidon.HelidonUtils.hasHelidonDependencies;
import static org.eclipse.jkube.helidon.HelidonUtils.hasHelidonGraalNativeImageExtension;

public class HelidonGenerator extends JavaExecGenerator {
public static final String HELIDON = "helidon";
public static final String DEFAULT_NATIVE_BASE_IMAGE = "registry.access.redhat.com/ubi8/ubi-minimal:8.7-1107";

public HelidonGenerator(GeneratorContext context) {
super(context, HELIDON);
}

@Override
public boolean isApplicable(List<ImageConfiguration> configs) {
return shouldAddGeneratedImageConfiguration(configs) && hasHelidonDependencies(getProject());
}

@Override
protected AssemblyConfiguration createAssembly() {
if (isNativeImage()) {
return HelidonAssemblies.NATIVE.createAssemblyConfiguration(this);
}
return HelidonAssemblies.STANDARD.createAssemblyConfiguration(this);
}

@Override
protected String getBuildWorkdir() {
if (isNativeImage()) {
return "/";
}
return getConfig(JavaExecGenerator.Config.TARGET_DIR);
}

@Override
protected String getFromAsConfigured() {
if (isNativeImage()) {
return Optional.ofNullable(super.getFromAsConfigured()).orElse(getNativeFrom());
}
return super.getFromAsConfigured();
}

@Override
protected Arguments getBuildEntryPoint() {
if (isNativeImage()) {
final Arguments.ArgumentsBuilder ab = Arguments.builder();
ab.execArgument("./" + getProject().getArtifactId());
getExtraJavaOptions().forEach(ab::execArgument);
return ab.build();
}
return null;
}

@Override
protected String getDefaultWebPort() {
return extractPort(getHelidonConfiguration(getProject()), super.getDefaultWebPort());
}

@Override
protected String getDefaultJolokiaPort() {
return isNativeImage() ? "0" : super.getDefaultJolokiaPort();
}

@Override
protected String getDefaultPrometheusPort() {
return isNativeImage() ? "0" : super.getDefaultPrometheusPort();
}

private String getNativeFrom() {
return DEFAULT_NATIVE_BASE_IMAGE;
}

private boolean isNativeImage() {
return hasHelidonGraalNativeImageExtension(getProject());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# The order of the generators used is defined in the active profile
# (which is the profile "default" by default)
# You can find the default profiles in "profiles-default.yml"

org.eclipse.jkube.helidon.generator.HelidonGenerator
Loading

0 comments on commit 684df4a

Please sign in to comment.