mirror of
https://github.com/jlengrand/quarkus.git
synced 2026-03-10 08:41:22 +00:00
feat (#5493): Add support for building and deploying container to Kubernetes.
This commit is contained in:
@@ -33,7 +33,9 @@ import io.quarkus.deployment.builditem.LaunchModeBuildItem;
|
||||
import io.quarkus.deployment.builditem.LiveReloadBuildItem;
|
||||
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.BuildSystemTargetBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.ContainerImageResultBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.DeploymentResultBuildItem;
|
||||
import io.quarkus.runtime.LaunchMode;
|
||||
|
||||
public class QuarkusAugmentor {
|
||||
@@ -107,7 +109,9 @@ public class QuarkusAugmentor {
|
||||
chainBuilder.addFinal(i);
|
||||
}
|
||||
chainBuilder.addFinal(GeneratedClassBuildItem.class)
|
||||
.addFinal(GeneratedResourceBuildItem.class);
|
||||
.addFinal(GeneratedResourceBuildItem.class)
|
||||
.addFinal(ContainerImageResultBuildItem.class)
|
||||
.addFinal(DeploymentResultBuildItem.class);
|
||||
|
||||
for (Consumer<BuildChainBuilder> i : buildChainCustomizers) {
|
||||
i.accept(chainBuilder);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
package io.quarkus.deployment.pkg;
|
||||
|
||||
import io.quarkus.runtime.annotations.ConfigItem;
|
||||
import io.quarkus.runtime.annotations.ConfigRoot;
|
||||
|
||||
@ConfigRoot
|
||||
public class ContainerConfig {
|
||||
|
||||
/**
|
||||
* Flag that specifies if container build is enabled
|
||||
*/
|
||||
@ConfigItem
|
||||
public boolean build;
|
||||
|
||||
/**
|
||||
* Flag that specifies if container deploy is enabled
|
||||
*/
|
||||
@ConfigItem
|
||||
public boolean deploy;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
package io.quarkus.deployment.pkg.builditem;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.quarkus.builder.item.SimpleBuildItem;
|
||||
|
||||
public final class DeploymentResultBuildItem extends SimpleBuildItem {
|
||||
|
||||
private final String name;
|
||||
private final Map<String, String> labels;
|
||||
|
||||
public DeploymentResultBuildItem(String name, Map<String, String> labels) {
|
||||
this.name = name;
|
||||
this.labels = labels;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Map<String, String> getLabels() {
|
||||
return this.labels;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
package io.quarkus.deployment.pkg.builditem;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import io.quarkus.deployment.pkg.ContainerConfig;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
|
||||
public class DockerBuild implements BooleanSupplier {
|
||||
|
||||
private final ContainerConfig containerConfig;
|
||||
|
||||
DockerBuild(ContainerConfig containerConfig) {
|
||||
this.containerConfig = containerConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
return containerConfig.build && ExecUtil.exec("docker", "version");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
package io.quarkus.deployment.pkg.builditem;
|
||||
|
||||
import io.quarkus.builder.item.SimpleBuildItem;
|
||||
|
||||
public final class DockerImageBuildItem extends SimpleBuildItem {
|
||||
|
||||
private final String image;
|
||||
|
||||
public DockerImageBuildItem(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return this.image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
package io.quarkus.deployment.pkg.builditem;
|
||||
|
||||
import io.quarkus.builder.item.SimpleBuildItem;
|
||||
|
||||
public final class DockerImageResultBuildItem extends SimpleBuildItem {
|
||||
|
||||
private final String imageId;
|
||||
private final String repository;
|
||||
private final String tag;
|
||||
|
||||
public DockerImageResultBuildItem(String imageId, String repository, String tag) {
|
||||
this.imageId = imageId;
|
||||
this.repository = repository;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getImageId() {
|
||||
return this.imageId;
|
||||
}
|
||||
|
||||
public String getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
package io.quarkus.deployment.pkg.steps;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.DockerBuild;
|
||||
import io.quarkus.deployment.pkg.builditem.DockerImageBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.DockerImageResultBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.JarBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.ModuleDirBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.NativeImageBuildItem;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
|
||||
public class DockerBuildStep {
|
||||
|
||||
private static final Logger log = Logger.getLogger(DockerBuildStep.class);
|
||||
|
||||
@BuildStep(onlyIf = DockerBuild.class, onlyIfNot = NativeBuild.class)
|
||||
public DockerImageResultBuildItem dockerBuildFromJar(ApplicationInfoBuildItem app, ModuleDirBuildItem moduledir,
|
||||
Optional<DockerImageBuildItem> dockerImage,
|
||||
JarBuildItem artifact) {
|
||||
log.info("Building docker image for jar.");
|
||||
ExecUtil.exec(moduledir.getPath().toFile(),
|
||||
"docker", "build",
|
||||
"-f",
|
||||
moduledir.getPath().resolve("src").resolve("main").resolve("docker").resolve("Dockerfile.jvm").toAbsolutePath()
|
||||
.toString(),
|
||||
"-t", dockerImage.map(d -> d.getImage()).orElse(app.getName() + ":" + app.getVersion()),
|
||||
moduledir.getPath().toAbsolutePath().toString());
|
||||
|
||||
return new DockerImageResultBuildItem(null, null, null);
|
||||
}
|
||||
|
||||
@BuildStep(onlyIf = { DockerBuild.class, NativeBuild.class })
|
||||
public DockerImageResultBuildItem dockerBuildFromNaticeImage(ApplicationInfoBuildItem app, ModuleDirBuildItem moduledir,
|
||||
Optional<DockerImageBuildItem> dockerImage,
|
||||
NativeImageBuildItem nativeImage) {
|
||||
log.info("Building docker image for native image.");
|
||||
ExecUtil.exec(moduledir.getPath().toFile(),
|
||||
"docker", "build",
|
||||
"-f",
|
||||
moduledir.getPath().resolve("src").resolve("main").resolve("docker").resolve("Dockerfile.native")
|
||||
.toAbsolutePath()
|
||||
.toString(),
|
||||
"-t", dockerImage.map(d -> d.getImage()).orElse(app.getName() + ":" + app.getVersion() + "-native"),
|
||||
moduledir.getPath().toAbsolutePath().toString());
|
||||
return new DockerImageResultBuildItem(null, null, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
package io.quarkus.deployment.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class ExecUtil {
|
||||
|
||||
/**
|
||||
* Execute the specified command from within the current directory.
|
||||
*
|
||||
* @param command The command
|
||||
* @param args The command arguments
|
||||
* @return true if commands where executed successfully
|
||||
*/
|
||||
public static boolean exec(String command, String... args) {
|
||||
return exec(new File("."), command, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the specified command from within the specified directory.
|
||||
*
|
||||
* @param directory The directory
|
||||
* @param command The command
|
||||
* @param args The command arguments
|
||||
* @return true if commands where executed successfully
|
||||
*/
|
||||
public static boolean exec(File directory, String command, String... args) {
|
||||
Process process = null;
|
||||
try {
|
||||
String[] cmd = new String[args.length + 1];
|
||||
cmd[0] = command;
|
||||
if (args.length > 0) {
|
||||
System.arraycopy(args, 0, cmd, 1, args.length);
|
||||
}
|
||||
process = new ProcessBuilder()
|
||||
.directory(directory)
|
||||
.command(cmd)
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
|
||||
try (InputStreamReader isr = new InputStreamReader(process.getInputStream());
|
||||
BufferedReader reader = new BufferedReader(isr)) {
|
||||
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
System.out.println(line);
|
||||
}
|
||||
process.waitFor();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
if (process != null) {
|
||||
return process.exitValue() == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
38
extensions/container/deployment/pom.xml
Normal file
38
extensions/container/deployment/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>quarkus-container-parent</artifactId>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<version>999-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>quarkus-container-deployment</artifactId>
|
||||
<name>Quarkus - Container - Deployment</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-core-deployment</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
package io.quarkus.container.deployment;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import io.quarkus.deployment.pkg.ContainerConfig;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
|
||||
public class DockerBuild implements BooleanSupplier {
|
||||
|
||||
private final ContainerConfig containerConfig;
|
||||
|
||||
DockerBuild(ContainerConfig containerConfig) {
|
||||
this.containerConfig = containerConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (containerConfig.build) {
|
||||
try {
|
||||
return ExecUtil.exec("docker", "version");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
|
||||
package io.quarkus.container.deployment;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.ContainerImageBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.ContainerImageResultBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.JarBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.NativeImageBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
|
||||
import io.quarkus.deployment.pkg.steps.NativeBuild;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
import io.quarkus.deployment.util.ImageUtil;
|
||||
|
||||
public class DockerBuildStep {
|
||||
|
||||
private static final Logger log = Logger.getLogger(DockerBuildStep.class);
|
||||
private static final String DOCKERFILE_JVM = "Dockerfile.jvm";
|
||||
private static final String DOCKERFILE_NATIVE = "Dockerfile.native";
|
||||
|
||||
@BuildStep(onlyIf = DockerBuild.class, onlyIfNot = NativeBuild.class)
|
||||
public ContainerImageResultBuildItem dockerBuildFromJar(ApplicationInfoBuildItem app,
|
||||
OutputTargetBuildItem out,
|
||||
Optional<ContainerImageBuildItem> dockerImage,
|
||||
JarBuildItem artifact) {
|
||||
log.info("Building docker image for jar.");
|
||||
String image = dockerImage.map(d -> d.getImage()).orElse(app.getName() + ":" + app.getVersion());
|
||||
ImageIdReader reader = new ImageIdReader();
|
||||
Path dockerFile = extractDockerfile(DOCKERFILE_JVM);
|
||||
ExecUtil.exec(out.getOutputDirectory().toFile(),
|
||||
reader,
|
||||
"docker", "build",
|
||||
"-f",
|
||||
dockerFile.resolve(DOCKERFILE_JVM).toAbsolutePath().toString(),
|
||||
"-t", image,
|
||||
out.getOutputDirectory().toAbsolutePath().toString());
|
||||
|
||||
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(image), ImageUtil.getTag(image));
|
||||
}
|
||||
|
||||
@BuildStep(onlyIf = { DockerBuild.class, NativeBuild.class })
|
||||
public ContainerImageResultBuildItem dockerBuildFromNativeImage(ApplicationInfoBuildItem app,
|
||||
OutputTargetBuildItem out,
|
||||
Optional<ContainerImageBuildItem> dockerImage,
|
||||
NativeImageBuildItem nativeImage) {
|
||||
log.info("Building docker image for native image.");
|
||||
String image = dockerImage.map(d -> d.getImage()).orElse(app.getName() + ":" + app.getVersion() + "-native");
|
||||
Path dockerFile = extractDockerfile(DOCKERFILE_NATIVE);
|
||||
ImageIdReader reader = new ImageIdReader();
|
||||
ExecUtil.exec(out.getOutputDirectory().toFile(),
|
||||
reader,
|
||||
"docker", "build",
|
||||
"-f",
|
||||
dockerFile.resolve(DOCKERFILE_NATIVE).toAbsolutePath().toString(),
|
||||
"-t", image,
|
||||
out.getOutputDirectory().toAbsolutePath().toString());
|
||||
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(image), ImageUtil.getTag(image));
|
||||
}
|
||||
|
||||
private Path extractDockerfile(String resource) {
|
||||
final Path path;
|
||||
try {
|
||||
path = Files.createTempDirectory("quarkus-docker");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Unable to setup environment for generating docker resources", e);
|
||||
}
|
||||
|
||||
try (InputStream jvm = getClass().getClassLoader().getResource(resource).openStream()) {
|
||||
Files.copy(jvm, path.resolve(resource), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Unable to extract docker resource: " + resource, e);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that creates a command output reader, that reads and holds the image id from the docker build output.
|
||||
*/
|
||||
private class ImageIdReader implements Function<InputStream, Runnable> {
|
||||
|
||||
private final AtomicReference<String> id = new AtomicReference<>();
|
||||
|
||||
public String getImageId() {
|
||||
return id.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable apply(InputStream t) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try (InputStreamReader isr = new InputStreamReader(t);
|
||||
BufferedReader reader = new BufferedReader(isr)) {
|
||||
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
if (line.startsWith("Succesfully built")) {
|
||||
String[] parts = line.split(" ");
|
||||
if (parts.length == 3)
|
||||
id.set(parts[2]);
|
||||
}
|
||||
log.info(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||
#
|
||||
# Before building the docker image run:
|
||||
#
|
||||
# mvn package
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/stm-quickstart-jvm .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/stm-quickstart-jvm
|
||||
#
|
||||
# Test the endpoint:
|
||||
#
|
||||
# curl -XPOST http://localhost:8080/stm
|
||||
# java -jar ../stress/target/codeone-stress-1.0.jar requests=100 parallelism=50 url=/stm
|
||||
# curl -XGET http://localhost:8080/stm
|
||||
#
|
||||
###
|
||||
FROM fabric8/java-alpine-openjdk8-jre
|
||||
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||
ENV AB_ENABLED=jmx_exporter
|
||||
COPY lib/* /deployments/lib/
|
||||
COPY *-runner.jar /deployments/app.jar
|
||||
ENTRYPOINT [ "/deployments/run-java.sh" ]
|
||||
@@ -0,0 +1,24 @@
|
||||
####
|
||||
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
|
||||
#
|
||||
# Before building the docker image run:
|
||||
#
|
||||
# mvn package -Pnative -Dquarkus.native.container-build=true
|
||||
#
|
||||
# Then, build the image with:
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile.native -t quarkus/hello-cloud .
|
||||
#
|
||||
# Then run the container using:
|
||||
#
|
||||
# docker run -i --rm -p 8080:8080 quarkus/hello-cloud
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal
|
||||
WORKDIR /work/
|
||||
COPY *-runner /work/application
|
||||
RUN chmod 775 /work
|
||||
EXPOSE 8080
|
||||
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
||||
~
|
||||
~
|
||||
21
extensions/container/pom.xml
Normal file
21
extensions/container/pom.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>quarkus-build-parent</artifactId>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<version>999-SNAPSHOT</version>
|
||||
<relativePath>../../build-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>quarkus-container-parent</artifactId>
|
||||
<name>Quarkus - Container</name>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>deployment</module>
|
||||
<module>runtime</module>
|
||||
<module>spi</module>
|
||||
</modules>
|
||||
</project>
|
||||
38
extensions/container/runtime/pom.xml
Normal file
38
extensions/container/runtime/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-container-parent</artifactId>
|
||||
<version>999-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>quarkus-container</artifactId>
|
||||
<name>Quarkus - Container - Runtime</name>
|
||||
<description>Manage container builds</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: "Docker"
|
||||
metadata:
|
||||
keywords:
|
||||
- "docker"
|
||||
guide: "https://quarkus.io/guides/docker"
|
||||
categories:
|
||||
- "cloud"
|
||||
status: "stable"
|
||||
21
extensions/container/spi/pom.xml
Normal file
21
extensions/container/spi/pom.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>quarkus-container-parent</artifactId>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<version>999-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>quarkus-container-spi</artifactId>
|
||||
<name>Quarkus - Container - SPI</name>
|
||||
<description>Extensions that provide Container features should include this module and the corresponding BuildItems</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-core-deployment</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
package io.quarkus.kubernetes.deployment;
|
||||
|
||||
import io.quarkus.runtime.annotations.ConfigItem;
|
||||
import io.quarkus.runtime.annotations.ConfigRoot;
|
||||
|
||||
@ConfigRoot
|
||||
public class KubernetesConfig {
|
||||
|
||||
private static final String KUBERNETES = "kubernetes";
|
||||
private static final String OPENSHIFT = "openshift";
|
||||
private static final String KNATIVE = "knative";
|
||||
|
||||
/**
|
||||
* The target deployment platform.
|
||||
* Defaults to kubernetes. Can be kubernetes, openshift, knative or any combination of the above as coma separated list.
|
||||
*/
|
||||
@ConfigItem(defaultValue = KUBERNETES)
|
||||
String deploymentTarget = KUBERNETES;
|
||||
|
||||
public String getDeploymentTarget() {
|
||||
return this.deploymentTarget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
package io.quarkus.kubernetes.deployment;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import io.quarkus.container.deployment.ContainerConfig;
|
||||
import io.quarkus.container.deployment.DockerBuild.OutputFilter;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
|
||||
public class KubernetesDeploy implements BooleanSupplier {
|
||||
|
||||
private KubernetesConfig kubernetesConfig;
|
||||
private ContainerConfig containerConfig;
|
||||
|
||||
KubernetesDeploy(ContainerConfig containerConfig, KubernetesConfig kubernetesConfig) {
|
||||
this.containerConfig = containerConfig;
|
||||
this.kubernetesConfig = kubernetesConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (containerConfig.deploy) {
|
||||
try {
|
||||
if (kubernetesConfig.getDeploymentTarget().contains(DeploymentTarget.OPENSHIFT)) {
|
||||
return ExecUtil.exec("oc", "version");
|
||||
}
|
||||
return ExecUtil.exec("kubectl", "version");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
package io.quarkus.kubernetes.deployment;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import io.dekorate.deps.kubernetes.api.model.HasMetadata;
|
||||
import io.dekorate.deps.kubernetes.api.model.KubernetesList;
|
||||
import io.dekorate.deps.kubernetes.client.KubernetesClient;
|
||||
import io.dekorate.utils.Clients;
|
||||
import io.dekorate.utils.Serialization;
|
||||
import io.quarkus.container.spi.ContainerImageResultBuildItem;
|
||||
import io.quarkus.deployment.IsNormal;
|
||||
import io.quarkus.deployment.annotations.BuildProducer;
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.DeploymentResultBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.DockerImageResultBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
|
||||
public class KubernetesDeployer {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(KubernetesDeployer.class);
|
||||
|
||||
@BuildStep(onlyIf = { IsNormal.class, KubernetesDeploy.class })
|
||||
public void deploy(KubernetesClientBuildItem kubernetesClient,
|
||||
ApplicationInfoBuildItem applicationInfo,
|
||||
Optional<ContainerImageResultBuildItem> containerImage,
|
||||
OutputTargetBuildItem outputTarget,
|
||||
BuildProducer<DeploymentResultBuildItem> deploymentResult) {
|
||||
|
||||
kubernetesConfig.getDeploymentTarget().stream().map(Enum::name).map(String::toLowerCase).findFirst().ifPresent(d -> {
|
||||
LOG.info("Deploying to " + d + ".");
|
||||
ExecUtil.exec(outputTarget.getOutputDirectory().toFile(), "oc", "apply", "-f",
|
||||
"kubernetes/" + d + ".yml");
|
||||
});
|
||||
|
||||
return new DeploymentResultBuildItem(null, null);
|
||||
}
|
||||
|
||||
public void setKubernetesconfig(KubernetesConfig kubernetesConfig) {
|
||||
this.kubernetesConfig = kubernetesConfig;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import org.eclipse.microprofile.config.ConfigProvider;
|
||||
|
||||
import io.dekorate.Session;
|
||||
import io.dekorate.SessionWriter;
|
||||
import io.dekorate.kubernetes.config.ImageConfiguration;
|
||||
import io.dekorate.kubernetes.config.PortBuilder;
|
||||
import io.dekorate.kubernetes.config.ProbeBuilder;
|
||||
import io.dekorate.kubernetes.configurator.AddPort;
|
||||
@@ -29,11 +30,13 @@ import io.dekorate.kubernetes.decorator.AddLivenessProbeDecorator;
|
||||
import io.dekorate.kubernetes.decorator.AddReadinessProbeDecorator;
|
||||
import io.dekorate.kubernetes.decorator.AddRoleBindingResourceDecorator;
|
||||
import io.dekorate.kubernetes.decorator.AddServiceAccountResourceDecorator;
|
||||
import io.dekorate.kubernetes.decorator.ApplyImageDecorator;
|
||||
import io.dekorate.kubernetes.decorator.ApplyServiceAccountNamedDecorator;
|
||||
import io.dekorate.processor.SimpleFileWriter;
|
||||
import io.dekorate.project.BuildInfo;
|
||||
import io.dekorate.project.FileProjectFactory;
|
||||
import io.dekorate.project.Project;
|
||||
import io.dekorate.utils.Images;
|
||||
import io.dekorate.utils.Maps;
|
||||
import io.dekorate.utils.Strings;
|
||||
import io.quarkus.deployment.IsNormal;
|
||||
@@ -44,6 +47,7 @@ import io.quarkus.deployment.builditem.ArchiveRootBuildItem;
|
||||
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
||||
import io.quarkus.deployment.builditem.GeneratedFileSystemResourceBuildItem;
|
||||
import io.quarkus.deployment.pkg.PackageConfig;
|
||||
import io.quarkus.deployment.pkg.builditem.ContainerImageBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
|
||||
import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
|
||||
import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
|
||||
@@ -77,6 +81,7 @@ class KubernetesProcessor {
|
||||
PackageConfig packageConfig,
|
||||
List<KubernetesRoleBuildItem> kubernetesRoleBuildItems,
|
||||
List<KubernetesPortBuildItem> kubernetesPortBuildItems,
|
||||
Optional<ContainerImageBuildItem> containerImageBuildItem,
|
||||
Optional<KubernetesHealthLivenessPathBuildItem> kubernetesHealthLivenessPathBuildItem,
|
||||
Optional<KubernetesHealthReadinessPathBuildItem> kubernetesHealthReadinessPathBuildItem)
|
||||
throws UnsupportedEncodingException {
|
||||
@@ -136,8 +141,10 @@ class KubernetesProcessor {
|
||||
session.setWriter(sessionWriter);
|
||||
|
||||
session.feed(Maps.fromProperties(configAsMap));
|
||||
|
||||
//apply build item configurations to the dekorate session.
|
||||
applyBuildItems(session, applicationInfo, kubernetesRoleBuildItems, kubernetesPortBuildItems,
|
||||
containerImageBuildItem,
|
||||
kubernetesHealthLivenessPathBuildItem,
|
||||
kubernetesHealthReadinessPathBuildItem);
|
||||
|
||||
@@ -181,9 +188,12 @@ class KubernetesProcessor {
|
||||
private void applyBuildItems(Session session, ApplicationInfoBuildItem applicationInfo,
|
||||
List<KubernetesRoleBuildItem> kubernetesRoleBuildItems,
|
||||
List<KubernetesPortBuildItem> kubernetesPortBuildItems,
|
||||
Optional<ContainerImageBuildItem> containerImageResultItem,
|
||||
Optional<KubernetesHealthLivenessPathBuildItem> kubernetesHealthLivenessPathBuildItem,
|
||||
Optional<KubernetesHealthReadinessPathBuildItem> kubernetesHealthReadinessPathBuildItem) {
|
||||
|
||||
containerImageResultItem.ifPresent(c -> session.resources()
|
||||
.decorate(new ApplyImageDecorator(applicationInfo.getName(), c.getImage())));
|
||||
//Handle ports
|
||||
final Map<String, Integer> ports = verifyPorts(kubernetesPortBuildItems);
|
||||
ports.entrySet().stream()
|
||||
@@ -245,7 +255,7 @@ class KubernetesProcessor {
|
||||
|
||||
/**
|
||||
* Returns the name of the generators that can handle the specified key.
|
||||
*
|
||||
*
|
||||
* @param key The key.
|
||||
* @return The generator name or null if the key format is unexpected.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user