mirror of
https://github.com/jlengrand/quarkus.git
synced 2026-03-10 08:41:22 +00:00
refactor: Move KubernetesClientBuildConfig to an spi module so that it
can be used by other extensions.
This commit is contained in:
@@ -478,7 +478,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-docker-spi</artifactId>
|
||||
<artifactId>quarkus-container-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -491,6 +491,11 @@
|
||||
<artifactId>quarkus-kubernetes-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kubernetes-client-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kubernetes-client-deployment</artifactId>
|
||||
|
||||
@@ -33,7 +33,6 @@ 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;
|
||||
@@ -110,7 +109,6 @@ public class QuarkusAugmentor {
|
||||
}
|
||||
chainBuilder.addFinal(GeneratedClassBuildItem.class)
|
||||
.addFinal(GeneratedResourceBuildItem.class)
|
||||
.addFinal(ContainerImageResultBuildItem.class)
|
||||
.addFinal(DeploymentResultBuildItem.class);
|
||||
|
||||
for (Consumer<BuildChainBuilder> i : buildChainCustomizers) {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -17,6 +17,10 @@
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-core-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-container-spi</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package io.quarkus.container.deployment;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import io.quarkus.runtime.annotations.ConfigItem;
|
||||
import io.quarkus.runtime.annotations.ConfigRoot;
|
||||
|
||||
@ConfigRoot
|
||||
public class ContainerConfig {
|
||||
|
||||
/**
|
||||
* The container registry to use
|
||||
*/
|
||||
@ConfigItem
|
||||
public Optional<String> registry;
|
||||
|
||||
/**
|
||||
* The group the container image will be part of
|
||||
*/
|
||||
@ConfigItem(defaultValue = "${user.name}")
|
||||
public String group;
|
||||
|
||||
/**
|
||||
* The name of the container image. If not set defaults to the application name
|
||||
*/
|
||||
@ConfigItem
|
||||
public Optional<String> name;
|
||||
|
||||
/**
|
||||
* The tag of the container image. If not set defaults to the application version
|
||||
*/
|
||||
@ConfigItem
|
||||
public Optional<String> tag;
|
||||
/**
|
||||
* 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,35 @@
|
||||
package io.quarkus.container.deployment;
|
||||
|
||||
import io.quarkus.container.deployment.util.ImageUtil;
|
||||
import io.quarkus.container.spi.ContainerImageBuildItem;
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
|
||||
import io.quarkus.deployment.pkg.steps.NativeBuild;
|
||||
|
||||
public class ContainerProcessor {
|
||||
|
||||
private ContainerConfig containerConfig;
|
||||
|
||||
@BuildStep(onlyIfNot = NativeBuild.class)
|
||||
public ContainerImageBuildItem publishImageInfo(ApplicationInfoBuildItem app) {
|
||||
String image = ImageUtil.getImage(containerConfig.registry, containerConfig.group,
|
||||
containerConfig.name.orElse(app.getName()), containerConfig.tag.orElse(app.getVersion()));
|
||||
return new ContainerImageBuildItem(image);
|
||||
}
|
||||
|
||||
@BuildStep(onlyIf = NativeBuild.class)
|
||||
public ContainerImageBuildItem publishNativeImageInfo(ApplicationInfoBuildItem app) {
|
||||
String image = ImageUtil.getImage(containerConfig.registry, containerConfig.group,
|
||||
containerConfig.name.orElse(app.getName()), containerConfig.tag.orElse(app.getVersion() + "-native"));
|
||||
return new ContainerImageBuildItem(image);
|
||||
}
|
||||
|
||||
public ContainerConfig getContainerConfig() {
|
||||
return this.containerConfig;
|
||||
}
|
||||
|
||||
public void setContainerConfig(ContainerConfig containerConfig) {
|
||||
this.containerConfig = containerConfig;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,23 @@
|
||||
|
||||
package io.quarkus.container.deployment;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import io.quarkus.deployment.pkg.ContainerConfig;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
|
||||
public class DockerBuild implements BooleanSupplier {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(DockerBuild.class.getName());
|
||||
private static boolean daemonFound = false;
|
||||
|
||||
private final ContainerConfig containerConfig;
|
||||
|
||||
DockerBuild(ContainerConfig containerConfig) {
|
||||
@@ -17,12 +27,48 @@ public class DockerBuild implements BooleanSupplier {
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (containerConfig.build) {
|
||||
//No need to perform the check multiple times.
|
||||
if (daemonFound) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
return ExecUtil.exec("docker", "version");
|
||||
OutputFilter filter = new OutputFilter();
|
||||
if (ExecUtil.exec(new File("."), filter, "docker", "version", "--format", "'{{.Server.Version}}'")) {
|
||||
LOGGER.info("Docker daemon found! Version:" + filter.getOutput());
|
||||
daemonFound = true;
|
||||
return true;
|
||||
} else {
|
||||
LOGGER.warn("Could not connect to docker daemon!");
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Could not connect to docker daemon!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class OutputFilter implements Function<InputStream, Runnable> {
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public Runnable apply(InputStream is) {
|
||||
return () -> {
|
||||
try (InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader reader = new BufferedReader(isr)) {
|
||||
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
builder.append(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error reading stream.", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String getOutput() {
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,22 +8,27 @@ import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import io.quarkus.container.deployment.util.ImageUtil;
|
||||
import io.quarkus.container.spi.ContainerImageBuildItem;
|
||||
import io.quarkus.container.spi.ContainerImageResultBuildItem;
|
||||
import io.quarkus.deployment.annotations.BuildProducer;
|
||||
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.ArtifactResultBuildItem;
|
||||
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 {
|
||||
|
||||
@@ -31,13 +36,14 @@ public class DockerBuildStep {
|
||||
private static final String DOCKERFILE_JVM = "Dockerfile.jvm";
|
||||
private static final String DOCKERFILE_NATIVE = "Dockerfile.native";
|
||||
|
||||
@Inject
|
||||
BuildProducer<ArtifactResultBuildItem> artifact;
|
||||
|
||||
@BuildStep(onlyIf = DockerBuild.class, onlyIfNot = NativeBuild.class)
|
||||
public ContainerImageResultBuildItem dockerBuildFromJar(ApplicationInfoBuildItem app,
|
||||
OutputTargetBuildItem out,
|
||||
Optional<ContainerImageBuildItem> dockerImage,
|
||||
JarBuildItem artifact) {
|
||||
ContainerImageBuildItem containerImage, JarBuildItem jar) {
|
||||
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(),
|
||||
@@ -45,19 +51,21 @@ public class DockerBuildStep {
|
||||
"docker", "build",
|
||||
"-f",
|
||||
dockerFile.resolve(DOCKERFILE_JVM).toAbsolutePath().toString(),
|
||||
"-t", image,
|
||||
"-t", containerImage.getImage(),
|
||||
out.getOutputDirectory().toAbsolutePath().toString());
|
||||
|
||||
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(image), ImageUtil.getTag(image));
|
||||
artifact.produce(new ArtifactResultBuildItem(null, "jar-container", new HashMap<String, Path>()));
|
||||
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(containerImage.getImage()),
|
||||
ImageUtil.getTag(containerImage.getImage()));
|
||||
}
|
||||
|
||||
@BuildStep(onlyIf = { DockerBuild.class, NativeBuild.class })
|
||||
public ContainerImageResultBuildItem dockerBuildFromNativeImage(ApplicationInfoBuildItem app,
|
||||
ContainerImageBuildItem containerImage,
|
||||
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(),
|
||||
@@ -65,9 +73,11 @@ public class DockerBuildStep {
|
||||
"docker", "build",
|
||||
"-f",
|
||||
dockerFile.resolve(DOCKERFILE_NATIVE).toAbsolutePath().toString(),
|
||||
"-t", image,
|
||||
"-t", containerImage.getImage(),
|
||||
out.getOutputDirectory().toAbsolutePath().toString());
|
||||
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(image), ImageUtil.getTag(image));
|
||||
artifact.produce(new ArtifactResultBuildItem(null, "native-container", new HashMap<String, Path>()));
|
||||
return new ContainerImageResultBuildItem(reader.getImageId(), ImageUtil.getRepository(containerImage.getImage()),
|
||||
ImageUtil.getTag(containerImage.getImage()));
|
||||
}
|
||||
|
||||
private Path extractDockerfile(String resource) {
|
||||
@@ -120,4 +130,5 @@ public class DockerBuildStep {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,37 @@
|
||||
|
||||
package io.quarkus.deployment.util;
|
||||
package io.quarkus.container.deployment.util;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ImageUtil {
|
||||
|
||||
private static final String SLASH = "/";
|
||||
private static final String COLN = ":";
|
||||
|
||||
/**
|
||||
* Create an image from the individual parts.
|
||||
*
|
||||
* @param registry The registry.
|
||||
* @param repository The repository.
|
||||
* @param name The name.
|
||||
* @param tag The tag.
|
||||
* @return The image.
|
||||
*/
|
||||
public static String getImage(Optional<String> registry, String repository, String name, String tag) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
throw new IllegalArgumentException("Docker image name cannot be null!");
|
||||
}
|
||||
if (tag == null || tag.isEmpty()) {
|
||||
throw new IllegalArgumentException("Docker image tag cannot be null!");
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
registry.ifPresent(r -> sb.append(r).append(SLASH));
|
||||
sb.append(repository).append(SLASH);
|
||||
|
||||
sb.append(name).append(COLN).append(tag);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the registry part of the docker image.
|
||||
*
|
||||
@@ -3,11 +3,11 @@
|
||||
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>
|
||||
<artifactId>quarkus-container-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>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
package io.quarkus.deployment.pkg.builditem;
|
||||
package io.quarkus.container.spi;
|
||||
|
||||
import io.quarkus.builder.item.SimpleBuildItem;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
package io.quarkus.deployment.pkg.builditem;
|
||||
package io.quarkus.container.spi;
|
||||
|
||||
import io.quarkus.builder.item.SimpleBuildItem;
|
||||
|
||||
@@ -26,5 +25,4 @@ public final class ContainerImageResultBuildItem extends SimpleBuildItem {
|
||||
public String getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,10 @@
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kubernetes-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kubernetes-client-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.quarkus.kubernetes.client.deployment;
|
||||
|
||||
import static io.quarkus.kubernetes.client.runtime.KubernetesClientUtils.*;
|
||||
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
import io.quarkus.kubernetes.client.runtime.KubernetesClientBuildConfig;
|
||||
import io.quarkus.kubernetes.client.spi.KubernetesClientBuildItem;
|
||||
|
||||
public class KubernetesClientBuildStep {
|
||||
|
||||
private KubernetesClientBuildConfig buildConfig;
|
||||
|
||||
@BuildStep
|
||||
public KubernetesClientBuildItem process() {
|
||||
return new KubernetesClientBuildItem(createClient(buildConfig));
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
<modules>
|
||||
<module>deployment</module>
|
||||
<module>runtime</module>
|
||||
<module>spi</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
||||
@@ -14,138 +14,139 @@ public class KubernetesClientBuildConfig {
|
||||
* Whether or not the client should trust a self signed certificate if so presented by the API server
|
||||
*/
|
||||
@ConfigItem(defaultValue = "false")
|
||||
boolean trustCerts;
|
||||
public boolean trustCerts;
|
||||
|
||||
/**
|
||||
* URL of the Kubernetes API server
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> masterUrl;
|
||||
public Optional<String> masterUrl;
|
||||
|
||||
/**
|
||||
* Default namespace to use
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> namespace;
|
||||
public Optional<String> namespace;
|
||||
|
||||
/**
|
||||
* CA certificate file
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> caCertFile;
|
||||
public Optional<String> caCertFile;
|
||||
|
||||
/**
|
||||
* CA certificate data
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> caCertData;
|
||||
public Optional<String> caCertData;
|
||||
|
||||
/**
|
||||
* Client certificate file
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> clientCertFile;
|
||||
public Optional<String> clientCertFile;
|
||||
|
||||
/**
|
||||
* Client certificate data
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> clientCertData;
|
||||
public Optional<String> clientCertData;
|
||||
|
||||
/**
|
||||
* Client key file
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> clientKeyFile;
|
||||
public Optional<String> clientKeyFile;
|
||||
|
||||
/**
|
||||
* Client key data
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> clientKeyData;
|
||||
public Optional<String> clientKeyData;
|
||||
|
||||
/**
|
||||
* Client key algorithm
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> clientKeyAlgo;
|
||||
public Optional<String> clientKeyAlgo;
|
||||
|
||||
/**
|
||||
* Client key passphrase
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> clientKeyPassphrase;
|
||||
public Optional<String> clientKeyPassphrase;
|
||||
|
||||
/**
|
||||
* Kubernetes auth username
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> username;
|
||||
public Optional<String> username;
|
||||
|
||||
/**
|
||||
* Kubernetes auth password
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> password;
|
||||
public Optional<String> password;
|
||||
|
||||
/**
|
||||
* Watch reconnect interval
|
||||
*/
|
||||
@ConfigItem(defaultValue = "PT1S") // default lifted from Kubernetes Client
|
||||
Duration watchReconnectInterval;
|
||||
public Duration watchReconnectInterval;
|
||||
|
||||
/**
|
||||
* Maximum reconnect attempts in case of watch failure
|
||||
* By default there is no limit to the number of reconnect attempts
|
||||
*/
|
||||
@ConfigItem(defaultValue = "-1") // default lifted from Kubernetes Client
|
||||
int watchReconnectLimit;
|
||||
public int watchReconnectLimit;
|
||||
|
||||
/**
|
||||
* Maximum amount of time to wait for a connection with the API server to be established
|
||||
*/
|
||||
@ConfigItem(defaultValue = "PT10S") // default lifted from Kubernetes Client
|
||||
Duration connectionTimeout;
|
||||
public Duration connectionTimeout;
|
||||
|
||||
/**
|
||||
* Maximum amount of time to wait for a request to the API server to be completed
|
||||
*/
|
||||
@ConfigItem(defaultValue = "PT10S") // default lifted from Kubernetes Client
|
||||
Duration requestTimeout;
|
||||
public Duration requestTimeout;
|
||||
|
||||
/**
|
||||
* Maximum amount of time in milliseconds to wait for a rollout to be completed
|
||||
*/
|
||||
@ConfigItem(defaultValue = "PT15M") // default lifted from Kubernetes Client
|
||||
Duration rollingTimeout;
|
||||
public Duration rollingTimeout;
|
||||
|
||||
/**
|
||||
* HTTP proxy used to access the Kubernetes API server
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> httpProxy;
|
||||
public Optional<String> httpProxy;
|
||||
|
||||
/**
|
||||
* HTTPS proxy used to access the Kubernetes API server
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> httpsProxy;
|
||||
public Optional<String> httpsProxy;
|
||||
|
||||
/**
|
||||
* Proxy username
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> proxyUsername;
|
||||
public Optional<String> proxyUsername;
|
||||
|
||||
/**
|
||||
* Proxy password
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String> proxyPassword;
|
||||
public Optional<String> proxyPassword;
|
||||
|
||||
/**
|
||||
* IP addresses or hosts to exclude from proxying
|
||||
*/
|
||||
@ConfigItem
|
||||
Optional<String[]> noProxy;
|
||||
public Optional<String[]> noProxy;
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import javax.enterprise.inject.Produces;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.ConfigBuilder;
|
||||
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.quarkus.arc.DefaultBean;
|
||||
@@ -19,33 +18,7 @@ public class KubernetesClientProducer {
|
||||
@Singleton
|
||||
@Produces
|
||||
public Config config() {
|
||||
Config base = Config.autoConfigure(null);
|
||||
return new ConfigBuilder(base)
|
||||
.withTrustCerts(buildConfig.trustCerts)
|
||||
.withWatchReconnectInterval((int) buildConfig.watchReconnectInterval.toMillis())
|
||||
.withWatchReconnectLimit(buildConfig.watchReconnectLimit)
|
||||
.withConnectionTimeout((int) buildConfig.connectionTimeout.toMillis())
|
||||
.withRequestTimeout((int) buildConfig.requestTimeout.toMillis())
|
||||
.withRollingTimeout(buildConfig.rollingTimeout.toMillis())
|
||||
.withMasterUrl(buildConfig.masterUrl.orElse(base.getMasterUrl()))
|
||||
.withNamespace(buildConfig.namespace.orElse(base.getNamespace()))
|
||||
.withUsername(buildConfig.username.orElse(base.getUsername()))
|
||||
.withPassword(buildConfig.password.orElse(base.getPassword()))
|
||||
.withCaCertFile(buildConfig.caCertFile.orElse(base.getCaCertFile()))
|
||||
.withCaCertData(buildConfig.caCertData.orElse(base.getCaCertData()))
|
||||
.withClientCertFile(buildConfig.clientCertFile.orElse(base.getClientCertFile()))
|
||||
.withClientCertData(buildConfig.clientCertData.orElse(base.getClientCertData()))
|
||||
.withClientKeyFile(buildConfig.clientKeyFile.orElse(base.getClientKeyFile()))
|
||||
.withClientKeyData(buildConfig.clientKeyData.orElse(base.getClientKeyData()))
|
||||
.withClientKeyPassphrase(buildConfig.clientKeyPassphrase.orElse(base.getClientKeyPassphrase()))
|
||||
.withClientKeyAlgo(buildConfig.clientKeyAlgo.orElse(base.getClientKeyAlgo()))
|
||||
.withHttpProxy(buildConfig.httpProxy.orElse(base.getHttpProxy()))
|
||||
.withHttpsProxy(buildConfig.httpsProxy.orElse(base.getHttpsProxy()))
|
||||
.withProxyUsername(buildConfig.proxyUsername.orElse(base.getProxyUsername()))
|
||||
.withProxyPassword(buildConfig.proxyPassword.orElse(base.getProxyPassword()))
|
||||
.withNoProxy(buildConfig.noProxy.isPresent() ? buildConfig.noProxy.get() : base.getNoProxy())
|
||||
.build();
|
||||
|
||||
return KubernetesClientUtils.createConfig(buildConfig);
|
||||
}
|
||||
|
||||
@DefaultBean
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package io.quarkus.kubernetes.client.runtime;
|
||||
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.ConfigBuilder;
|
||||
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
|
||||
public class KubernetesClientUtils {
|
||||
|
||||
public static Config createConfig(KubernetesClientBuildConfig buildConfig) {
|
||||
Config base = new Config();
|
||||
return new ConfigBuilder()
|
||||
.withTrustCerts(buildConfig.trustCerts)
|
||||
.withWatchReconnectInterval((int) buildConfig.watchReconnectInterval.toMillis())
|
||||
.withWatchReconnectLimit(buildConfig.watchReconnectLimit)
|
||||
.withConnectionTimeout((int) buildConfig.connectionTimeout.toMillis())
|
||||
.withRequestTimeout((int) buildConfig.requestTimeout.toMillis())
|
||||
.withRollingTimeout(buildConfig.rollingTimeout.toMillis())
|
||||
.withMasterUrl(buildConfig.masterUrl.orElse(base.getMasterUrl()))
|
||||
.withNamespace(buildConfig.namespace.orElse(base.getNamespace()))
|
||||
.withUsername(buildConfig.username.orElse(base.getUsername()))
|
||||
.withPassword(buildConfig.password.orElse(base.getPassword()))
|
||||
.withCaCertFile(buildConfig.caCertFile.orElse(base.getCaCertFile()))
|
||||
.withCaCertData(buildConfig.caCertData.orElse(base.getCaCertData()))
|
||||
.withClientCertFile(buildConfig.clientCertFile.orElse(base.getClientCertFile()))
|
||||
.withClientCertData(buildConfig.clientCertData.orElse(base.getClientCertData()))
|
||||
.withClientKeyFile(buildConfig.clientKeyFile.orElse(base.getClientKeyFile()))
|
||||
.withClientKeyData(buildConfig.clientKeyData.orElse(base.getClientKeyData()))
|
||||
.withClientKeyPassphrase(buildConfig.clientKeyPassphrase.orElse(base.getClientKeyPassphrase()))
|
||||
.withClientKeyAlgo(buildConfig.clientKeyAlgo.orElse(base.getClientKeyAlgo()))
|
||||
.withHttpProxy(buildConfig.httpProxy.orElse(base.getHttpProxy()))
|
||||
.withHttpsProxy(buildConfig.httpsProxy.orElse(base.getHttpsProxy()))
|
||||
.withProxyUsername(buildConfig.proxyUsername.orElse(base.getProxyUsername()))
|
||||
.withProxyPassword(buildConfig.proxyPassword.orElse(base.getProxyPassword()))
|
||||
.withNoProxy(buildConfig.noProxy.isPresent() ? buildConfig.noProxy.get() : base.getNoProxy())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static KubernetesClient createClient(KubernetesClientBuildConfig buildConfig) {
|
||||
return new DefaultKubernetesClient(createConfig(buildConfig));
|
||||
}
|
||||
}
|
||||
57
extensions/kubernetes-client/spi/pom.xml
Normal file
57
extensions/kubernetes-client/spi/pom.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<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-kubernetes-parent</artifactId>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<version>999-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>quarkus-kubernetes-client-spi</artifactId>
|
||||
<name>Quarkus - Kubernetes Client - SPI</name>
|
||||
<description>Extensions that use the Kubernetes client, use this module to
|
||||
configure the client instance</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-core-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>kubernetes-client</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</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,18 @@
|
||||
package io.quarkus.kubernetes.client.spi;
|
||||
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.quarkus.builder.item.SimpleBuildItem;
|
||||
|
||||
public final class KubernetesClientBuildItem extends SimpleBuildItem {
|
||||
|
||||
private final KubernetesClient client;
|
||||
|
||||
public KubernetesClientBuildItem(KubernetesClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public KubernetesClient getClient() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,10 +17,18 @@
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-container-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-container-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kubernetes-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-kubernetes-client-deployment</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dekorate</groupId>
|
||||
<artifactId>kubernetes-annotations</artifactId>
|
||||
|
||||
@@ -3,8 +3,17 @@ package io.quarkus.kubernetes.deployment;
|
||||
|
||||
public enum DeploymentTarget {
|
||||
|
||||
KUBERNETES,
|
||||
OPENSHIFT,
|
||||
KNATIVE
|
||||
KUBERNETES("Deployment"),
|
||||
OPENSHIFT("DeploymentConfig"),
|
||||
KNATIVE("Service");
|
||||
|
||||
private String kind;
|
||||
|
||||
DeploymentTarget(String kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
return this.kind;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
|
||||
package io.quarkus.kubernetes.deployment;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import io.quarkus.container.deployment.ContainerConfig;
|
||||
import io.quarkus.container.deployment.DockerBuild.OutputFilter;
|
||||
@@ -9,6 +20,8 @@ import io.quarkus.deployment.util.ExecUtil;
|
||||
|
||||
public class KubernetesDeploy implements BooleanSupplier {
|
||||
|
||||
private final Logger LOGGER = Logger.getLogger(KubernetesDeploy.class);
|
||||
|
||||
private KubernetesConfig kubernetesConfig;
|
||||
private ContainerConfig containerConfig;
|
||||
|
||||
@@ -20,15 +33,65 @@ public class KubernetesDeploy implements BooleanSupplier {
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (containerConfig.deploy) {
|
||||
OutputFilter filter = new OutputFilter();
|
||||
try {
|
||||
if (kubernetesConfig.getDeploymentTarget().contains(DeploymentTarget.OPENSHIFT)) {
|
||||
return ExecUtil.exec("oc", "version");
|
||||
if (ExecUtil.exec(new File("."), filter, "oc", "version")) {
|
||||
Optional<String> version = getServerVersionFromOc(filter.getLines());
|
||||
version.ifPresent(v -> LOGGER.info("Found Kubernetes version:" + v));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ExecUtil.exec(new File("."), filter, "kubectl", "version")) {
|
||||
Optional<String> version = getServerVersionFromKubectl(filter.getLines());
|
||||
version.ifPresent(v -> LOGGER.info("Found Kubernetes version:" + v));
|
||||
return true;
|
||||
}
|
||||
return ExecUtil.exec("kubectl", "version");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Optional<String> getServerVersionFromOc(List<String> lines) {
|
||||
return lines.stream()
|
||||
.filter(l -> l.startsWith("kubernetes"))
|
||||
.map(l -> l.split(" "))
|
||||
.filter(a -> a.length > 2)
|
||||
.map(a -> a[1])
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private static Optional<String> getServerVersionFromKubectl(List<String> lines) {
|
||||
return lines.stream()
|
||||
.filter(l -> l.startsWith("Server Version"))
|
||||
.map(l -> l.split("\""))
|
||||
.filter(a -> a.length > 5)
|
||||
.map(a -> a[5])
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private static class OutputFilter implements Function<InputStream, Runnable> {
|
||||
private final List<String> list = new ArrayList();
|
||||
|
||||
@Override
|
||||
public Runnable apply(InputStream is) {
|
||||
return () -> {
|
||||
try (InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader reader = new BufferedReader(isr)) {
|
||||
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
list.add(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error reading stream.", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public List<String> getLines() {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
|
||||
package io.quarkus.kubernetes.deployment;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import io.dekorate.deps.kubernetes.api.model.HasMetadata;
|
||||
@@ -13,10 +20,9 @@ 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.ContainerImageResultBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.DeploymentResultBuildItem;
|
||||
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
|
||||
import io.quarkus.deployment.util.ExecUtil;
|
||||
import io.quarkus.kubernetes.client.spi.KubernetesClientBuildItem;
|
||||
|
||||
public class KubernetesDeployer {
|
||||
|
||||
@@ -29,13 +35,26 @@ public class KubernetesDeployer {
|
||||
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 kubernetesConfig.getDeploymentTarget().stream().findFirst().map(d -> {
|
||||
String namespace = Optional.of(kubernetesClient.getClient().getNamespace()).orElse("default");
|
||||
|
||||
return new DeploymentResultBuildItem(null, null);
|
||||
LOG.info("Deploying to " + d.name().toLowerCase() + "in namespace:" + namespace + ".");
|
||||
File manifest = outputTarget.getOutputDirectory().resolve("kubernetes").resolve(d.name().toLowerCase() + ".yml")
|
||||
.toFile();
|
||||
try (FileInputStream fis = new FileInputStream(manifest)) {
|
||||
List<HasMetadata> resources = kubernetesClient.getClient().load(fis).inNamespace(namespace).createOrReplace();
|
||||
HasMetadata m = resources.stream()
|
||||
.filter(r -> r.getKind().equals(d.getKind()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException(
|
||||
"No " + d.getKind() + " found under: " + manifest.getAbsolutePath()));
|
||||
return new DeploymentResultBuildItem(m.getMetadata().getName(), m.getMetadata().getLabels());
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IllegalStateException("Can't find generated kubernetes manifest: " + manifest.getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error closing file: " + manifest.getAbsolutePath());
|
||||
}
|
||||
}).get();
|
||||
}
|
||||
|
||||
public void setKubernetesconfig(KubernetesConfig kubernetesConfig) {
|
||||
|
||||
@@ -22,7 +22,6 @@ 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;
|
||||
@@ -36,9 +35,9 @@ 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.container.spi.ContainerImageBuildItem;
|
||||
import io.quarkus.deployment.IsNormal;
|
||||
import io.quarkus.deployment.annotations.BuildProducer;
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
@@ -47,7 +46,6 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user