diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index f1a9b5fb188f5..9d73e081b9c17 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -147,7 +147,7 @@
2.35.1
1.3.0
1.3.72
- 0.12.11
+ 0.13.2
0.10.0
2.14.6
3.0.1
diff --git a/extensions/container-image/spi/src/main/java/io/quarkus/container/spi/ContainerImageInfoBuildItem.java b/extensions/container-image/spi/src/main/java/io/quarkus/container/spi/ContainerImageInfoBuildItem.java
index cf49ccf9c618f..fd67ab86f1d7c 100644
--- a/extensions/container-image/spi/src/main/java/io/quarkus/container/spi/ContainerImageInfoBuildItem.java
+++ b/extensions/container-image/spi/src/main/java/io/quarkus/container/spi/ContainerImageInfoBuildItem.java
@@ -75,4 +75,8 @@ public Set getAdditionalTags() {
public String getRepository() {
return repository;
}
+
+ public String getGroup() {
+ return repository == null ? null : repository.split("/")[0];
+ }
}
diff --git a/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java b/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java
index 708663014f7e2..a7bee339301bd 100644
--- a/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java
+++ b/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java
@@ -1,17 +1,170 @@
package io.quarkus.minikube.deployment;
+import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT;
import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT;
+import static io.quarkus.kubernetes.deployment.Constants.HTTP_PORT;
+import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES;
+import static io.quarkus.kubernetes.deployment.Constants.MAX_NODE_PORT_VALUE;
+import static io.quarkus.kubernetes.deployment.Constants.MAX_PORT_NUMBER;
import static io.quarkus.kubernetes.deployment.Constants.MINIKUBE;
+import static io.quarkus.kubernetes.deployment.Constants.MIN_NODE_PORT_VALUE;
+import static io.quarkus.kubernetes.deployment.Constants.MIN_PORT_NUMBER;
+import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.DEFAULT_PRIORITY;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import io.dekorate.kubernetes.annotation.ServiceType;
+import io.dekorate.kubernetes.config.EnvBuilder;
+import io.dekorate.kubernetes.decorator.AddEnvVarDecorator;
+import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator;
+import io.dekorate.kubernetes.decorator.ApplyImagePullPolicyDecorator;
+import io.dekorate.project.Project;
+import io.quarkus.container.spi.BaseImageInfoBuildItem;
+import io.quarkus.container.spi.ContainerImageInfoBuildItem;
+import io.quarkus.container.spi.ContainerImageLabelBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
+import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
+import io.quarkus.deployment.pkg.PackageConfig;
+import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
+import io.quarkus.kubernetes.deployment.AddNodePortDecorator;
+import io.quarkus.kubernetes.deployment.ApplyContainerImageDecorator;
+import io.quarkus.kubernetes.deployment.ApplyHttpGetActionPortDecorator;
+import io.quarkus.kubernetes.deployment.ApplyServiceTypeDecorator;
+import io.quarkus.kubernetes.deployment.EnvConverter;
+import io.quarkus.kubernetes.deployment.KubernetesCommonHelper;
+import io.quarkus.kubernetes.deployment.KubernetesConfig;
+import io.quarkus.kubernetes.deployment.ResourceNameUtil;
+import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
+import io.quarkus.kubernetes.spi.DecoratorBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem;
import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesEnvBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;
public class MinikubeProcessor {
+ public static final String DEFAULT_HASH_ALGORITHM = "SHA-256";
+ private static final int MINIKUBE_PRIORITY = DEFAULT_PRIORITY + 20;
+
+ @BuildStep
+ public void checkMinikube(BuildProducer deploymentTargets) {
+ deploymentTargets.produce(new KubernetesDeploymentTargetBuildItem(MINIKUBE, DEPLOYMENT, MINIKUBE_PRIORITY, true));
+ }
+
+ @BuildStep
+ public void createAnnotations(KubernetesConfig config, BuildProducer annotations) {
+ config.getAnnotations().forEach((k, v) -> {
+ annotations.produce(new KubernetesAnnotationBuildItem(k, v, MINIKUBE));
+ });
+ }
+
@BuildStep
- public void checkOpenshift(BuildProducer deploymentTargets) {
- deploymentTargets
- .produce(new KubernetesDeploymentTargetBuildItem(MINIKUBE, DEPLOYMENT, true));
+ public void createLabels(KubernetesConfig config, BuildProducer labels,
+ BuildProducer imageLabels) {
+ config.getLabels().forEach((k, v) -> {
+ labels.produce(new KubernetesLabelBuildItem(k, v, MINIKUBE));
+ imageLabels.produce(new ContainerImageLabelBuildItem(k, v));
+ });
}
+
+ @BuildStep
+ public List createConfigurators(KubernetesConfig config, List ports) {
+ List result = new ArrayList<>();
+ result.addAll(KubernetesCommonHelper.createPlatformConfigurators(config));
+ result.addAll(KubernetesCommonHelper.createGlobalConfigurators(ports));
+ return result;
+
+ }
+
+ @BuildStep
+ public List createDecorators(ApplicationInfoBuildItem applicationInfo,
+ OutputTargetBuildItem outputTarget,
+ KubernetesConfig config,
+ PackageConfig packageConfig,
+ Optional metricsConfiguration,
+ List annotations,
+ List labels,
+ List envs,
+ Optional baseImage,
+ Optional image,
+ Optional command,
+ List ports,
+ Optional livenessPath,
+ Optional readinessPath,
+ List roles,
+ List roleBindings) {
+
+ List result = new ArrayList<>();
+ String name = ResourceNameUtil.getResourceName(config, applicationInfo);
+
+ Project project = KubernetesCommonHelper.createProject(applicationInfo, outputTarget, packageConfig);
+ result.addAll(KubernetesCommonHelper.createDecorators(project, MINIKUBE, name, config, metricsConfiguration,
+ annotations, labels, command,
+ ports, livenessPath, readinessPath, roles, roleBindings));
+
+ image.ifPresent(i -> {
+ result.add(new DecoratorBuildItem(MINIKUBE, new ApplyContainerImageDecorator(name, i.getImage())));
+ });
+
+ Stream.concat(config.convertToBuildItems().stream(),
+ envs.stream().filter(e -> e.getTarget() == null || KUBERNETES.equals(e.getTarget()))).forEach(e -> {
+ result.add(new DecoratorBuildItem(MINIKUBE,
+ new AddEnvVarDecorator(ApplicationContainerDecorator.ANY, name, new EnvBuilder()
+ .withName(EnvConverter.convertName(e.getName()))
+ .withValue(e.getValue())
+ .withSecret(e.getSecret())
+ .withConfigmap(e.getConfigMap())
+ .withField(e.getField())
+ .build())));
+ });
+
+ result.add(new DecoratorBuildItem(MINIKUBE, new ApplyImagePullPolicyDecorator(name, "IfNotPresent")));
+
+ //Service handling
+ result.add(new DecoratorBuildItem(MINIKUBE, new ApplyServiceTypeDecorator(name, ServiceType.NodePort.name())));
+ result.add(new DecoratorBuildItem(MINIKUBE, new AddNodePortDecorator(name, config.getNodePort()
+ .orElseGet(() -> getStablePortNumberInRange(name, MIN_NODE_PORT_VALUE, MAX_NODE_PORT_VALUE)))));
+
+ //Probe port handling
+ Integer port = ports.stream().filter(p -> HTTP_PORT.equals(p.getName())).map(KubernetesPortBuildItem::getPort)
+ .findFirst().orElse(DEFAULT_HTTP_PORT);
+ result.add(new DecoratorBuildItem(MINIKUBE, new ApplyHttpGetActionPortDecorator(port)));
+
+ return result;
+ }
+
+ /**
+ * Given a string, generate a port number within the supplied range
+ * The output is always the same (between {@code min} and {@code max})
+ * given the same input and it's useful when we need to generate a port number
+ * which needs to stay the same but we don't care about the exact value
+ */
+ private int getStablePortNumberInRange(String input, int min, int max) {
+ if (min < MIN_PORT_NUMBER || max > MAX_PORT_NUMBER) {
+ throw new IllegalArgumentException(
+ String.format("Port number range must be within [%d-%d]", MIN_PORT_NUMBER, MAX_PORT_NUMBER));
+ }
+
+ try {
+ byte[] hash = MessageDigest.getInstance(DEFAULT_HASH_ALGORITHM).digest(input.getBytes(StandardCharsets.UTF_8));
+ return min + new BigInteger(hash).mod(BigInteger.valueOf(max - min)).intValue();
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to generate stable port number from input string: '" + input + "'", e);
+ }
+ }
+
}
diff --git a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/ConfiguratorBuildItem.java b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/ConfiguratorBuildItem.java
new file mode 100644
index 0000000000000..8eb01d10b9645
--- /dev/null
+++ b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/ConfiguratorBuildItem.java
@@ -0,0 +1,38 @@
+package io.quarkus.kubernetes.spi;
+
+import java.util.Optional;
+
+import io.quarkus.builder.item.MultiBuildItem;
+
+/**
+ * A build item that wraps around Configurator objects.
+ * The purpose of those build items is influence the configuration that will be feed to the generator process.
+ * Configurators are similar to decorators, but are applied to configuration instead of generated resources.
+ */
+public final class ConfiguratorBuildItem extends MultiBuildItem {
+
+ /**
+ * The configurator
+ */
+ private final Object configurator;
+
+ public ConfiguratorBuildItem(Object configurator) {
+ this.configurator = configurator;
+ }
+
+ public Object getConfigurator() {
+ return this.configurator;
+ }
+
+ public boolean matches(Class type) {
+ return type.isInstance(configurator);
+
+ }
+
+ public Optional getConfigurator(Class type) {
+ if (matches(type)) {
+ return Optional. of((C) configurator);
+ }
+ return Optional.empty();
+ }
+}
diff --git a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/DecoratorBuildItem.java b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/DecoratorBuildItem.java
index f037636e35035..c76bf15b64122 100644
--- a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/DecoratorBuildItem.java
+++ b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/DecoratorBuildItem.java
@@ -5,6 +5,10 @@
import io.quarkus.builder.item.MultiBuildItem;
+/**
+ * A build item that wraps around Decorator objects.
+ * The purpose of those build items is to perform modification on the generated resources.
+ */
public final class DecoratorBuildItem extends MultiBuildItem {
/**
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyImageGroupConfigurator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyImageGroupConfigurator.java
new file mode 100644
index 0000000000000..155961cf6c2cb
--- /dev/null
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyImageGroupConfigurator.java
@@ -0,0 +1,20 @@
+
+package io.quarkus.kubernetes.deployment;
+
+import io.dekorate.kubernetes.config.Configurator;
+import io.dekorate.kubernetes.config.ImageConfigurationFluent;
+
+public class ApplyImageGroupConfigurator extends Configurator> {
+
+ private final String group;
+
+ public ApplyImageGroupConfigurator(String group) {
+ this.group = group;
+ }
+
+ @Override
+ public void visit(ImageConfigurationFluent> config) {
+ config.withGroup(group);
+ }
+
+}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyImageRegistryConfigurator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyImageRegistryConfigurator.java
new file mode 100644
index 0000000000000..1d4106eaa3a0d
--- /dev/null
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyImageRegistryConfigurator.java
@@ -0,0 +1,19 @@
+
+package io.quarkus.kubernetes.deployment;
+
+import io.dekorate.kubernetes.config.Configurator;
+import io.dekorate.kubernetes.config.ImageConfigurationFluent;
+
+public class ApplyImageRegistryConfigurator extends Configurator> {
+
+ private final String registry;
+
+ public ApplyImageRegistryConfigurator(String registry) {
+ this.registry = registry;
+ }
+
+ @Override
+ public void visit(ImageConfigurationFluent> config) {
+ config.withRegistry(registry);
+ }
+}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java
index 393b63ef9c1db..db619fd12f565 100644
--- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java
@@ -2,7 +2,7 @@
public final class Constants {
- static final String KUBERNETES = "kubernetes";
+ public static final String KUBERNETES = "kubernetes";
public static final String MINIKUBE = "minikube";
public static final String DEPLOYMENT = "Deployment";
static final String DOCKER = "docker";
@@ -28,13 +28,13 @@ public final class Constants {
static final String QUARKUS_ANNOTATIONS_VCS_URL = "app.quarkus.io/vcs-url";
static final String QUARKUS_ANNOTATIONS_BUILD_TIMESTAMP = "app.quarkus.io/build-timestamp";
- static final String HTTP_PORT = "http";
- static final int DEFAULT_HTTP_PORT = 8080;
+ public static final String HTTP_PORT = "http";
+ public static final int DEFAULT_HTTP_PORT = 8080;
- static final int MIN_PORT_NUMBER = 1;
- static final int MAX_PORT_NUMBER = 65535;
- static final int MIN_NODE_PORT_VALUE = 30000;
- static final int MAX_NODE_PORT_VALUE = 31999;
+ public static final int MIN_PORT_NUMBER = 1;
+ public static final int MAX_PORT_NUMBER = 65535;
+ public static final int MIN_NODE_PORT_VALUE = 30000;
+ public static final int MAX_NODE_PORT_VALUE = 31999;
private Constants() {
}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ContainerAdapter.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ContainerAdapter.java
index a89b22e855883..70b254d16881c 100644
--- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ContainerAdapter.java
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ContainerAdapter.java
@@ -44,8 +44,7 @@ public static Container adapt(io.dekorate.kubernetes.config.Container container)
builder.accept(new AddMountDecorator(mount));
}
- builder.accept(new ApplyImagePullPolicyDecorator(container.getImagePullPolicy()));
-
+ builder.accept(new ApplyImagePullPolicyDecorator(name, container.getImagePullPolicy()));
builder.accept(new AddLivenessProbeDecorator(name, container.getLivenessProbe()));
builder.accept(new AddReadinessProbeDecorator(name, container.getReadinessProbe()));
return builder.build();
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DisableS2iConfigurator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DisableS2iConfigurator.java
new file mode 100644
index 0000000000000..a3d0c1e048387
--- /dev/null
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DisableS2iConfigurator.java
@@ -0,0 +1,13 @@
+
+package io.quarkus.kubernetes.deployment;
+
+import io.dekorate.kubernetes.config.Configurator;
+import io.dekorate.s2i.config.S2iBuildConfigFluent;
+
+public class DisableS2iConfigurator extends Configurator> {
+
+ @Override
+ public void visit(S2iBuildConfigFluent> s2i) {
+ s2i.withEnabled(false);
+ }
+}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java
new file mode 100644
index 0000000000000..bfd523b95131c
--- /dev/null
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java
@@ -0,0 +1,196 @@
+package io.quarkus.kubernetes.deployment;
+
+import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT;
+import static io.quarkus.kubernetes.deployment.Constants.KNATIVE;
+import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.DEFAULT_PRIORITY;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import io.dekorate.knative.decorator.ApplyGlobalAutoscalingClassDecorator;
+import io.dekorate.knative.decorator.ApplyGlobalContainerConcurrencyDecorator;
+import io.dekorate.knative.decorator.ApplyGlobalRequestsPerSecondTargetDecorator;
+import io.dekorate.knative.decorator.ApplyGlobalTargetUtilizationDecorator;
+import io.dekorate.knative.decorator.ApplyLocalAutoscalingClassDecorator;
+import io.dekorate.knative.decorator.ApplyLocalAutoscalingMetricDecorator;
+import io.dekorate.knative.decorator.ApplyLocalAutoscalingTargetDecorator;
+import io.dekorate.knative.decorator.ApplyLocalContainerConcurrencyDecorator;
+import io.dekorate.knative.decorator.ApplyLocalTargetUtilizationPercentageDecorator;
+import io.dekorate.knative.decorator.ApplyMaxScaleDecorator;
+import io.dekorate.knative.decorator.ApplyMinScaleDecorator;
+import io.dekorate.kubernetes.config.EnvBuilder;
+import io.dekorate.kubernetes.decorator.AddConfigMapDataDecorator;
+import io.dekorate.kubernetes.decorator.AddConfigMapResourceProvidingDecorator;
+import io.dekorate.kubernetes.decorator.AddEnvVarDecorator;
+import io.dekorate.kubernetes.decorator.AddLabelDecorator;
+import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator;
+import io.dekorate.project.Project;
+import io.quarkus.container.spi.BaseImageInfoBuildItem;
+import io.quarkus.container.spi.ContainerImageInfoBuildItem;
+import io.quarkus.container.spi.ContainerImageLabelBuildItem;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
+import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
+import io.quarkus.deployment.pkg.PackageConfig;
+import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
+import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
+import io.quarkus.kubernetes.spi.DecoratorBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesEnvBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;
+
+public class KnativeProcessor {
+
+ private static final int KNATIVE_PRIORITY = DEFAULT_PRIORITY;
+
+ @BuildStep
+ public void checkKnative(BuildProducer deploymentTargets) {
+ List targets = KubernetesConfigUtil.getUserSpecifiedDeploymentTargets();
+ deploymentTargets.produce(
+ new KubernetesDeploymentTargetBuildItem(KNATIVE, DEPLOYMENT, KNATIVE_PRIORITY, targets.contains(KNATIVE)));
+ }
+
+ @BuildStep
+ public void createAnnotations(KnativeConfig config, BuildProducer annotations) {
+ config.getAnnotations().forEach((k, v) -> {
+ annotations.produce(new KubernetesAnnotationBuildItem(k, v, KNATIVE));
+ });
+ }
+
+ @BuildStep
+ public void createLabels(KnativeConfig config, BuildProducer labels,
+ BuildProducer imageLabels) {
+ config.getLabels().forEach((k, v) -> {
+ labels.produce(new KubernetesLabelBuildItem(k, v, KNATIVE));
+ imageLabels.produce(new ContainerImageLabelBuildItem(k, v));
+ });
+ }
+
+ @BuildStep
+ public List createConfigurators(KnativeConfig config, List ports) {
+ List result = new ArrayList<>();
+ result.addAll(KubernetesCommonHelper.createPlatformConfigurators(config));
+ result.addAll(KubernetesCommonHelper.createGlobalConfigurators(ports));
+ return result;
+
+ }
+
+ @BuildStep
+ public List createDecorators(ApplicationInfoBuildItem applicationInfo,
+ OutputTargetBuildItem outputTarget,
+ KnativeConfig config,
+ PackageConfig packageConfig,
+ Optional metricsConfiguration,
+ List annotations,
+ List labels,
+ List envs,
+ Optional baseImage,
+ Optional image,
+ Optional command,
+ List ports,
+ Optional livenessPath,
+ Optional readinessPath,
+ List roles,
+ List roleBindings) {
+
+ List result = new ArrayList<>();
+ String name = ResourceNameUtil.getResourceName(config, applicationInfo);
+
+ Project project = KubernetesCommonHelper.createProject(applicationInfo, outputTarget, packageConfig);
+ result.addAll(KubernetesCommonHelper.createDecorators(project, KNATIVE, name, config, metricsConfiguration, annotations,
+ labels, command,
+ ports, livenessPath, readinessPath, roles, roleBindings));
+
+ image.ifPresent(i -> {
+ result.add(new DecoratorBuildItem(KNATIVE, new ApplyContainerImageDecorator(name, i.getImage())));
+ });
+
+ Stream.concat(config.convertToBuildItems().stream(),
+ envs.stream().filter(e -> e.getTarget() == null || KNATIVE.equals(e.getTarget()))).forEach(e -> {
+ result.add(new DecoratorBuildItem(KNATIVE,
+ new AddEnvVarDecorator(ApplicationContainerDecorator.ANY, name, new EnvBuilder()
+ .withName(EnvConverter.convertName(e.getName()))
+ .withValue(e.getValue())
+ .withSecret(e.getSecret())
+ .withConfigmap(e.getConfigMap())
+ .withField(e.getField())
+ .build())));
+ });
+
+ if (config.clusterLocal) {
+ result.add(new DecoratorBuildItem(KNATIVE,
+ new AddLabelDecorator(name, "serving.knative.dev/visibility", "cluster-local")));
+ }
+
+ config.minScale.ifPresent(min -> result.add(new DecoratorBuildItem(KNATIVE, new ApplyMinScaleDecorator(name, min))));
+
+ config.maxScale.ifPresent(max -> result.add(new DecoratorBuildItem(KNATIVE, new ApplyMaxScaleDecorator(name, max))));
+
+ config.revisionAutoScaling.autoScalerClass.map(AutoScalerClassConverter::convert)
+ .ifPresent(a -> result.add(new DecoratorBuildItem(KNATIVE, new ApplyLocalAutoscalingClassDecorator(name, a))));
+
+ config.revisionAutoScaling.metric.map(AutoScalingMetricConverter::convert)
+ .ifPresent(m -> result.add(new DecoratorBuildItem(KNATIVE, new ApplyLocalAutoscalingMetricDecorator(name, m))));
+
+ config.revisionAutoScaling.containerConcurrency
+ .ifPresent(
+ c -> result.add(new DecoratorBuildItem(KNATIVE, new ApplyLocalContainerConcurrencyDecorator(name, c))));
+
+ config.revisionAutoScaling.targetUtilizationPercentage
+ .ifPresent(t -> result
+ .add(new DecoratorBuildItem(KNATIVE, new ApplyLocalTargetUtilizationPercentageDecorator(name, t))));
+ config.revisionAutoScaling.target
+ .ifPresent(t -> result.add(new DecoratorBuildItem(KNATIVE, new ApplyLocalAutoscalingTargetDecorator(name, t))));
+
+ config.globalAutoScaling.autoScalerClass
+ .map(AutoScalerClassConverter::convert)
+ .ifPresent(a -> {
+ result.add(
+ new DecoratorBuildItem(KNATIVE, new AddConfigMapResourceProvidingDecorator("config-autoscaler")));
+ result.add(new DecoratorBuildItem(KNATIVE, new ApplyGlobalAutoscalingClassDecorator(a)));
+ });
+
+ config.globalAutoScaling.containerConcurrency
+ .ifPresent(c -> {
+ result.add(new DecoratorBuildItem(KNATIVE, new AddConfigMapResourceProvidingDecorator("config-defaults")));
+ result.add(new DecoratorBuildItem(KNATIVE, new ApplyGlobalContainerConcurrencyDecorator(c)));
+ });
+
+ config.globalAutoScaling.requestsPerSecond
+ .ifPresent(r -> {
+ result.add(
+ new DecoratorBuildItem(KNATIVE, new AddConfigMapResourceProvidingDecorator("config-autoscaler")));
+ result.add(new DecoratorBuildItem(KNATIVE, new ApplyGlobalRequestsPerSecondTargetDecorator(r)));
+ });
+
+ config.globalAutoScaling.targetUtilizationPercentage
+ .ifPresent(t -> {
+ result.add(
+ new DecoratorBuildItem(KNATIVE, new AddConfigMapResourceProvidingDecorator("config-autoscaler")));
+ result.add(new DecoratorBuildItem(KNATIVE, new ApplyGlobalTargetUtilizationDecorator(t)));
+ });
+
+ if (!config.scaleToZeroEnabled) {
+ result.add(new DecoratorBuildItem(KNATIVE, new AddConfigMapResourceProvidingDecorator("config-autoscaler")));
+ result.add(
+ new DecoratorBuildItem(KNATIVE, new AddConfigMapDataDecorator("config-autoscaler", "enable-scale-to-zero",
+ String.valueOf(config.scaleToZeroEnabled))));
+ }
+
+ result.add(new DecoratorBuildItem(KNATIVE, new ApplyServiceTypeDecorator(name, config.getServiceType().name())));
+
+ //In Knative its expected that all http ports in probe are ommitted (so we set them to null).
+ result.add(new DecoratorBuildItem(KNATIVE, new ApplyHttpGetActionPortDecorator(null)));
+ return result;
+ }
+}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java
new file mode 100644
index 0000000000000..859dcb2d39e89
--- /dev/null
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java
@@ -0,0 +1,364 @@
+
+package io.quarkus.kubernetes.deployment;
+
+import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_BUILD_TIMESTAMP;
+import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_COMMIT_ID;
+import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_VCS_URL;
+
+import java.nio.file.Path;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import io.dekorate.kubernetes.config.Annotation;
+import io.dekorate.kubernetes.config.PortBuilder;
+import io.dekorate.kubernetes.configurator.AddPort;
+import io.dekorate.kubernetes.decorator.AddAnnotationDecorator;
+import io.dekorate.kubernetes.decorator.AddAwsElasticBlockStoreVolumeDecorator;
+import io.dekorate.kubernetes.decorator.AddAzureDiskVolumeDecorator;
+import io.dekorate.kubernetes.decorator.AddAzureFileVolumeDecorator;
+import io.dekorate.kubernetes.decorator.AddConfigMapVolumeDecorator;
+import io.dekorate.kubernetes.decorator.AddHostAliasesDecorator;
+import io.dekorate.kubernetes.decorator.AddImagePullSecretDecorator;
+import io.dekorate.kubernetes.decorator.AddInitContainerDecorator;
+import io.dekorate.kubernetes.decorator.AddLabelDecorator;
+import io.dekorate.kubernetes.decorator.AddLivenessProbeDecorator;
+import io.dekorate.kubernetes.decorator.AddMountDecorator;
+import io.dekorate.kubernetes.decorator.AddPvcVolumeDecorator;
+import io.dekorate.kubernetes.decorator.AddReadinessProbeDecorator;
+import io.dekorate.kubernetes.decorator.AddRoleBindingResourceDecorator;
+import io.dekorate.kubernetes.decorator.AddSecretVolumeDecorator;
+import io.dekorate.kubernetes.decorator.AddServiceAccountResourceDecorator;
+import io.dekorate.kubernetes.decorator.ApplyArgsDecorator;
+import io.dekorate.kubernetes.decorator.ApplyCommandDecorator;
+import io.dekorate.kubernetes.decorator.ApplyServiceAccountNamedDecorator;
+import io.dekorate.kubernetes.decorator.ApplyWorkingDirDecorator;
+import io.dekorate.kubernetes.decorator.RemoveAnnotationDecorator;
+import io.dekorate.project.BuildInfo;
+import io.dekorate.project.FileProjectFactory;
+import io.dekorate.project.Project;
+import io.dekorate.project.ScmInfo;
+import io.dekorate.utils.Annotations;
+import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
+import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
+import io.quarkus.deployment.pkg.PackageConfig;
+import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
+import io.quarkus.kubernetes.deployment.Annotations.Prometheus;
+import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
+import io.quarkus.kubernetes.spi.DecoratorBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;
+
+public class KubernetesCommonHelper {
+
+ private static final String OUTPUT_ARTIFACT_FORMAT = "%s%s.jar";
+
+ public static Project createProject(ApplicationInfoBuildItem app, OutputTargetBuildItem outputTarget,
+ PackageConfig packageConfig) {
+ return createProject(app, outputTarget.getOutputDirectory()
+ .resolve(String.format(OUTPUT_ARTIFACT_FORMAT, outputTarget.getBaseName(), packageConfig.runnerSuffix)));
+ }
+
+ public static Project createProject(ApplicationInfoBuildItem app, Path artifactPath) {
+ //Let dekorate create a Project instance and then override with what is found in ApplicationInfoBuildItem.
+ Project project = FileProjectFactory.create(artifactPath.toFile());
+ BuildInfo buildInfo = new BuildInfo(app.getName(), app.getVersion(),
+ "jar", project.getBuildInfo().getBuildTool(),
+ project.getBuildInfo().getBuildToolVersion(),
+ artifactPath.toAbsolutePath(),
+ project.getBuildInfo().getClassOutputDir(),
+ project.getBuildInfo().getResourceDir());
+
+ return new Project(project.getRoot(), buildInfo, project.getScmInfo());
+ }
+
+ /**
+ * Creates the common configurator build items.
+ */
+ public static List createGlobalConfigurators(List ports) {
+ List result = new ArrayList<>();
+ verifyPorts(ports).entrySet().stream()
+ .map(e -> new PortBuilder().withName(e.getKey()).withContainerPort(e.getValue()).build())
+ .forEach(p -> result.add(new ConfiguratorBuildItem(new AddPort(p))));
+ return result;
+ }
+
+ /**
+ * Creates the common configurator build items.
+ */
+ public static List createPlatformConfigurators(PlatformConfiguration config) {
+ List result = new ArrayList<>();
+ config.getPorts().entrySet().forEach(e -> result.add(new ConfiguratorBuildItem(new AddPort(PortConverter.convert(e)))));
+ return result;
+ }
+
+ /**
+ * Creates the common decorator build items.
+ */
+ public static List createDecorators(Project project, String target, String name,
+ PlatformConfiguration config,
+ Optional metricsConfiguration,
+ List annotations,
+ List labels,
+ Optional command,
+ List ports,
+ Optional livenessProbePath,
+ Optional readinessProbePath,
+ List roles,
+ List roleBindings) {
+ List result = new ArrayList<>();
+
+ annotations.forEach(a -> {
+ result.add(new DecoratorBuildItem(a.getTarget(),
+ new AddAnnotationDecorator(name, a.getKey(), a.getValue())));
+ });
+
+ labels.forEach(l -> {
+ result.add(new DecoratorBuildItem(l.getTarget(),
+ new AddLabelDecorator(name, l.getKey(), l.getValue())));
+ });
+
+ result.addAll(createAnnotationDecorators(project, target, name, config, metricsConfiguration, ports));
+ result.addAll(createPodDecorators(project, target, name, config));
+ result.addAll(createContainerDecorators(project, target, name, config));
+ result.addAll(createMountAndVolumeDecorators(project, target, name, config));
+
+ //Handle Command and arguments
+ command.ifPresent(c -> {
+ result.add(new DecoratorBuildItem(new ApplyCommandDecorator(name, new String[] { c.getCommand() })));
+ result.add(new DecoratorBuildItem(new ApplyArgsDecorator(name, c.getArgs())));
+ });
+
+ //Handle Probes
+ result.addAll(createProbeDecorators(name, target, config.getLivenessProbe(), config.getReadinessProbe(),
+ livenessProbePath, readinessProbePath));
+
+ //Handle RBAC
+ if (!roleBindings.isEmpty()) {
+ result.add(new DecoratorBuildItem(new ApplyServiceAccountNamedDecorator()));
+ result.add(new DecoratorBuildItem(new AddServiceAccountResourceDecorator()));
+ roles.forEach(r -> result.add(new DecoratorBuildItem(new AddRoleResourceDecorator(r))));
+ roleBindings.forEach(rb -> result.add(new DecoratorBuildItem(
+ new AddRoleBindingResourceDecorator(rb.getName(), null, rb.getRole(), rb.isClusterWide()
+ ? AddRoleBindingResourceDecorator.RoleKind.ClusterRole
+ : AddRoleBindingResourceDecorator.RoleKind.Role))));
+ }
+
+ // The presence of optional is causing issues in OCP 3.11, so we better remove them.
+ // The following 4 decorator will set the optional property to null, so that it won't make it into the file.
+ result.add(new DecoratorBuildItem(target, new RemoveOptionalFromSecretEnvSourceDecorator()));
+ result.add(new DecoratorBuildItem(target, new RemoveOptionalFromConfigMapEnvSourceDecorator()));
+ result.add(new DecoratorBuildItem(target, new RemoveOptionalFromSecretKeySelectorDecorator()));
+ result.add(new DecoratorBuildItem(target, new RemoveOptionalFromConfigMapKeySelectorDecorator()));
+ return result;
+ }
+
+ /**
+ * Creates container decorator build items.
+ *
+ * @param target The deployment target (e.g. kubernetes, openshift, knative)
+ * @param name The name of the resource to accept the configuration
+ * @param config The {@link PlatformConfiguration} instance
+ */
+ private static List createContainerDecorators(Project project, String target, String name,
+ PlatformConfiguration config) {
+ List result = new ArrayList<>();
+ if (config.getNamespace().isPresent()) {
+ result.add(new DecoratorBuildItem(target, new AddNamespaceDecorator(config.getNamespace().get())));
+ }
+
+ config.getWorkingDir().ifPresent(w -> {
+ result.add(new DecoratorBuildItem(target, new ApplyWorkingDirDecorator(name, w)));
+ });
+
+ config.getCommand().ifPresent(c -> {
+ result.add(new DecoratorBuildItem(target, new ApplyCommandDecorator(name, c.toArray(new String[0]))));
+ });
+
+ config.getArguments().ifPresent(a -> {
+ result.add(new DecoratorBuildItem(target, new ApplyArgsDecorator(name, a.toArray(new String[0]))));
+ });
+
+ return result;
+ }
+
+ /**
+ * Creates pod decorator build items.
+ *
+ * @param target The deployment target (e.g. kubernetes, openshift, knative)
+ * @param name The name of the resource to accept the configuration
+ * @param config The {@link PlatformConfiguration} instance
+ */
+ private static List createPodDecorators(Project project, String target, String name,
+ PlatformConfiguration config) {
+ List result = new ArrayList<>();
+ config.getImagePullSecrets().ifPresent(l -> {
+ l.forEach(s -> result.add(new DecoratorBuildItem(target, new AddImagePullSecretDecorator(name, s))));
+ });
+
+ config.getHostAliases().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddHostAliasesDecorator(name, HostAliasConverter.convert(e))));
+ });
+
+ config.getServiceAccount().ifPresent(s -> {
+ result.add(new DecoratorBuildItem(target, new ApplyServiceAccountNamedDecorator(name, s)));
+ });
+
+ config.getInitContainers().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddInitContainerDecorator(name, ContainerConverter.convert(e))));
+ });
+
+ config.getSidecars().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddSidecarDecorator(name, ContainerConverter.convert(e))));
+ });
+
+ return result;
+ }
+
+ private static List createMountAndVolumeDecorators(Project project, String target, String name,
+ PlatformConfiguration config) {
+ List result = new ArrayList<>();
+ config.getMounts().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddMountDecorator(MountConverter.convert(e))));
+ });
+
+ config.getSecretVolumes().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddSecretVolumeDecorator(SecretVolumeConverter.convert(e))));
+ });
+
+ config.getConfigMapVolumes().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddConfigMapVolumeDecorator(ConfigMapVolumeConverter.convert(e))));
+ });
+
+ config.getPvcVolumes().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddPvcVolumeDecorator(PvcVolumeConverter.convert(e))));
+ });
+
+ config.getAwsElasticBlockStoreVolumes().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target,
+ new AddAwsElasticBlockStoreVolumeDecorator(AwsElasticBlockStoreVolumeConverter.convert(e))));
+ });
+
+ config.getAzureFileVolumes().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddAzureFileVolumeDecorator(AzureFileVolumeConverter.convert(e))));
+ });
+
+ config.getAzureDiskVolumes().entrySet().forEach(e -> {
+ result.add(new DecoratorBuildItem(target, new AddAzureDiskVolumeDecorator(AzureDiskVolumeConverter.convert(e))));
+ });
+ return result;
+ }
+
+ private static List createAnnotationDecorators(Project project, String target, String name,
+ PlatformConfiguration config,
+ Optional metricsConfiguration,
+ List ports) {
+ List result = new ArrayList<>();
+ ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
+
+ ScmInfo scm = project.getScmInfo();
+ String vcsUrl = scm != null ? scm.getUrl() : null;
+ String commitId = scm != null ? scm.getCommit() : null;
+
+ //Dekorate uses its own annotations. Let's replace them with the quarkus ones.
+ result.add(new DecoratorBuildItem(target, new RemoveAnnotationDecorator(Annotations.VCS_URL)));
+ result.add(new DecoratorBuildItem(target, new RemoveAnnotationDecorator(Annotations.COMMIT_ID)));
+
+ //Add quarkus vcs annotations
+ if (commitId != null) {
+ result.add(new DecoratorBuildItem(target,
+ new AddAnnotationDecorator(name, new Annotation(QUARKUS_ANNOTATIONS_COMMIT_ID, commitId, new String[0]))));
+ }
+ if (vcsUrl != null) {
+ result.add(new DecoratorBuildItem(target,
+ new AddAnnotationDecorator(name, new Annotation(QUARKUS_ANNOTATIONS_VCS_URL, vcsUrl, new String[0]))));
+ }
+
+ if (config.isAddBuildTimestamp()) {
+ result.add(new DecoratorBuildItem(target,
+ new AddAnnotationDecorator(name, new Annotation(QUARKUS_ANNOTATIONS_BUILD_TIMESTAMP,
+ now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd - HH:mm:ss Z")), new String[0]))));
+ }
+
+ metricsConfiguration.ifPresent(m -> {
+ String path = m.metricsEndpoint();
+ if (!ports.isEmpty() && path != null) {
+ result.add(new DecoratorBuildItem(target, new AddAnnotationDecorator(name, Prometheus.SCRAPE, "true")));
+ result.add(new DecoratorBuildItem(target, new AddAnnotationDecorator(name, Prometheus.PATH, path)));
+ result.add(new DecoratorBuildItem(target,
+ new AddAnnotationDecorator(name, Prometheus.PORT, "" + ports.get(0).getPort())));
+ }
+ });
+
+ //Add metrics annotations
+ return result;
+ }
+
+ private static List createProbeDecorators(String name, String target, ProbeConfig livenessProbe,
+ ProbeConfig readinessProbe,
+ Optional livenessPath,
+ Optional readinessPath) {
+ List result = new ArrayList<>();
+ createLivenessProbe(name, target, livenessProbe, livenessPath).ifPresent(d -> result.add(d));
+ createReadinessProbe(name, target, readinessProbe, readinessPath).ifPresent(d -> result.add(d));
+ return result;
+ }
+
+ private static Optional createLivenessProbe(String name, String target, ProbeConfig livenessProbe,
+ Optional livenessPath) {
+ if (livenessProbe.hasUserSuppliedAction()) {
+ return Optional.of(
+ new DecoratorBuildItem(target, new AddLivenessProbeDecorator(name, ProbeConverter.convert(livenessProbe))));
+ } else if (livenessPath.isPresent()) {
+ return Optional.of(new DecoratorBuildItem(target, new AddLivenessProbeDecorator(name,
+ ProbeConverter.builder(livenessProbe).withHttpActionPath(livenessPath.get().getPath()).build())));
+ }
+ return Optional.empty();
+ }
+
+ private static Optional createReadinessProbe(String name, String target, ProbeConfig readinessProbe,
+ Optional readinessPath) {
+ if (readinessProbe.hasUserSuppliedAction()) {
+ return Optional.of(new DecoratorBuildItem(target,
+ new AddReadinessProbeDecorator(name, ProbeConverter.convert(readinessProbe))));
+ } else if (readinessPath.isPresent()) {
+ return Optional.of(new DecoratorBuildItem(target, new AddReadinessProbeDecorator(name,
+ ProbeConverter.builder(readinessProbe).withHttpActionPath(readinessPath.get().getPath()).build())));
+ }
+ return Optional.empty();
+ }
+
+ private static Map verifyPorts(List kubernetesPortBuildItems) {
+ final Map result = new HashMap<>();
+ final Set usedPorts = new HashSet<>();
+ for (KubernetesPortBuildItem entry : kubernetesPortBuildItems) {
+ final String name = entry.getName();
+ if (result.containsKey(name)) {
+ throw new IllegalArgumentException(
+ "All Kubernetes ports must have unique names - " + name + "has been used multiple times");
+ }
+ final Integer port = entry.getPort();
+ if (usedPorts.contains(port)) {
+ throw new IllegalArgumentException(
+ "All Kubernetes ports must be unique - " + port + "has been used multiple times");
+ }
+ result.put(name, port);
+ usedPorts.add(port);
+ }
+ return result;
+ }
+
+}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java
index b356ff1cf7706..6aea94037205a 100644
--- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java
@@ -331,6 +331,10 @@ public ServiceType getServiceType() {
return serviceType;
}
+ public OptionalInt getNodePort() {
+ return this.nodePort;
+ }
+
public ImagePullPolicy getImagePullPolicy() {
return imagePullPolicy;
}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java
index 4807c4705dea9..b766ef65f8ced 100644
--- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java
@@ -1,48 +1,18 @@
package io.quarkus.kubernetes.deployment;
-import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT;
-import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_S2I_IMAGE_NAME;
-import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT;
-import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT_CONFIG;
-import static io.quarkus.kubernetes.deployment.Constants.HTTP_PORT;
-import static io.quarkus.kubernetes.deployment.Constants.KNATIVE;
import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES;
-import static io.quarkus.kubernetes.deployment.Constants.MAX_NODE_PORT_VALUE;
-import static io.quarkus.kubernetes.deployment.Constants.MAX_PORT_NUMBER;
-import static io.quarkus.kubernetes.deployment.Constants.MINIKUBE;
-import static io.quarkus.kubernetes.deployment.Constants.MIN_NODE_PORT_VALUE;
-import static io.quarkus.kubernetes.deployment.Constants.MIN_PORT_NUMBER;
-import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT;
-import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT_APP_RUNTIME;
-import static io.quarkus.kubernetes.deployment.Constants.QUARKUS;
-import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_BUILD_TIMESTAMP;
-import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_COMMIT_ID;
-import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_VCS_URL;
-import static io.quarkus.kubernetes.deployment.Constants.SERVICE;
-import static io.quarkus.kubernetes.deployment.ResourceNameUtil.getResourceName;
-import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.DEFAULT_PRIORITY;
-import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.VANILLA_KUBERNETES_PRIORITY;
import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.mergeList;
import java.io.File;
import java.io.IOException;
-import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.security.MessageDigest;
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -51,76 +21,14 @@
import io.dekorate.Session;
import io.dekorate.SessionReader;
import io.dekorate.SessionWriter;
-import io.dekorate.knative.decorator.ApplyGlobalAutoscalingClassDecorator;
-import io.dekorate.knative.decorator.ApplyGlobalContainerConcurrencyDecorator;
-import io.dekorate.knative.decorator.ApplyGlobalRequestsPerSecondTargetDecorator;
-import io.dekorate.knative.decorator.ApplyGlobalTargetUtilizationDecorator;
-import io.dekorate.knative.decorator.ApplyLocalAutoscalingClassDecorator;
-import io.dekorate.knative.decorator.ApplyLocalAutoscalingMetricDecorator;
-import io.dekorate.knative.decorator.ApplyLocalAutoscalingTargetDecorator;
-import io.dekorate.knative.decorator.ApplyLocalContainerConcurrencyDecorator;
-import io.dekorate.knative.decorator.ApplyLocalTargetUtilizationPercentageDecorator;
-import io.dekorate.knative.decorator.ApplyMaxScaleDecorator;
-import io.dekorate.knative.decorator.ApplyMinScaleDecorator;
-import io.dekorate.kubernetes.annotation.ImagePullPolicy;
-import io.dekorate.kubernetes.annotation.ServiceType;
-import io.dekorate.kubernetes.config.Annotation;
import io.dekorate.kubernetes.config.Configurator;
-import io.dekorate.kubernetes.config.EnvBuilder;
-import io.dekorate.kubernetes.config.ImageConfigurationFluent;
-import io.dekorate.kubernetes.config.Label;
-import io.dekorate.kubernetes.config.LabelBuilder;
-import io.dekorate.kubernetes.config.PortBuilder;
-import io.dekorate.kubernetes.configurator.AddPort;
-import io.dekorate.kubernetes.decorator.AddAnnotationDecorator;
-import io.dekorate.kubernetes.decorator.AddAwsElasticBlockStoreVolumeDecorator;
-import io.dekorate.kubernetes.decorator.AddAzureDiskVolumeDecorator;
-import io.dekorate.kubernetes.decorator.AddAzureFileVolumeDecorator;
-import io.dekorate.kubernetes.decorator.AddConfigMapDataDecorator;
-import io.dekorate.kubernetes.decorator.AddConfigMapResourceProvidingDecorator;
-import io.dekorate.kubernetes.decorator.AddConfigMapVolumeDecorator;
-import io.dekorate.kubernetes.decorator.AddEnvVarDecorator;
-import io.dekorate.kubernetes.decorator.AddHostAliasesDecorator;
-import io.dekorate.kubernetes.decorator.AddImagePullSecretDecorator;
-import io.dekorate.kubernetes.decorator.AddInitContainerDecorator;
-import io.dekorate.kubernetes.decorator.AddLabelDecorator;
-import io.dekorate.kubernetes.decorator.AddLivenessProbeDecorator;
-import io.dekorate.kubernetes.decorator.AddMountDecorator;
-import io.dekorate.kubernetes.decorator.AddPvcVolumeDecorator;
-import io.dekorate.kubernetes.decorator.AddReadinessProbeDecorator;
-import io.dekorate.kubernetes.decorator.AddRoleBindingResourceDecorator;
-import io.dekorate.kubernetes.decorator.AddSecretVolumeDecorator;
-import io.dekorate.kubernetes.decorator.AddServiceAccountResourceDecorator;
-import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator;
-import io.dekorate.kubernetes.decorator.ApplyArgsDecorator;
-import io.dekorate.kubernetes.decorator.ApplyCommandDecorator;
-import io.dekorate.kubernetes.decorator.ApplyImagePullPolicyDecorator;
-import io.dekorate.kubernetes.decorator.ApplyServiceAccountNamedDecorator;
-import io.dekorate.kubernetes.decorator.ApplyWorkingDirDecorator;
import io.dekorate.kubernetes.decorator.Decorator;
-import io.dekorate.kubernetes.decorator.RemoveAnnotationDecorator;
-import io.dekorate.kubernetes.decorator.RemoveFromMatchingLabelsDecorator;
-import io.dekorate.kubernetes.decorator.RemoveFromSelectorDecorator;
-import io.dekorate.kubernetes.decorator.RemoveLabelDecorator;
import io.dekorate.logger.NoopLogger;
import io.dekorate.processor.SimpleFileReader;
import io.dekorate.processor.SimpleFileWriter;
-import io.dekorate.project.BuildInfo;
-import io.dekorate.project.FileProjectFactory;
import io.dekorate.project.Project;
-import io.dekorate.project.ScmInfo;
-import io.dekorate.s2i.config.S2iBuildConfig;
-import io.dekorate.s2i.config.S2iBuildConfigBuilder;
-import io.dekorate.s2i.config.S2iBuildConfigFluent;
-import io.dekorate.s2i.decorator.AddBuilderImageStreamResourceDecorator;
-import io.dekorate.utils.Annotations;
-import io.dekorate.utils.Labels;
import io.dekorate.utils.Maps;
import io.dekorate.utils.Strings;
-import io.quarkus.container.image.deployment.util.ImageUtil;
-import io.quarkus.container.spi.BaseImageInfoBuildItem;
-import io.quarkus.container.spi.ContainerImageInfoBuildItem;
-import io.quarkus.container.spi.ContainerImageLabelBuildItem;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
@@ -129,22 +37,13 @@
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.GeneratedFileSystemResourceBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
-import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
import io.quarkus.deployment.pkg.PackageConfig;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.deployment.util.FileUtil;
-import io.quarkus.kubernetes.deployment.Annotations.Prometheus;
+import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
import io.quarkus.kubernetes.spi.DecoratorBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem;
import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesEnvBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem;
import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
-import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;
import io.quarkus.runtime.LaunchMode;
class KubernetesProcessor {
@@ -154,42 +53,11 @@ class KubernetesProcessor {
private static final String OUTPUT_ARTIFACT_FORMAT = "%s%s.jar";
public static final String DEFAULT_HASH_ALGORITHM = "SHA-256";
- private static final int MINIKUBE_PRIORITY = DEFAULT_PRIORITY + 20;
- private static final int OPENSHIFT_PRIORITY = DEFAULT_PRIORITY + 10;
- private static final int KNATIVE_PRIORITY = DEFAULT_PRIORITY;
-
@BuildStep
FeatureBuildItem produceFeature() {
return new FeatureBuildItem(Feature.KUBERNETES);
}
- @BuildStep
- public void deploymentTargets(BuildProducer deploymentTargets) {
- List userSpecifiedDeploymentTargets = KubernetesConfigUtil.getUserSpecifiedDeploymentTargets();
- if (userSpecifiedDeploymentTargets.isEmpty()) {
- // when nothing was selected by the user, we enable vanilla Kubernetes by default
- deploymentTargets.produce(
- new KubernetesDeploymentTargetBuildItem(KUBERNETES, DEPLOYMENT, VANILLA_KUBERNETES_PRIORITY, true));
- }
-
- // even if these are disabled, they serve the purpose of setting the proper priorities
-
- deploymentTargets
- .produce(new KubernetesDeploymentTargetBuildItem(MINIKUBE, DEPLOYMENT, MINIKUBE_PRIORITY,
- userSpecifiedDeploymentTargets.contains(MINIKUBE)));
-
- deploymentTargets
- .produce(new KubernetesDeploymentTargetBuildItem(OPENSHIFT, DEPLOYMENT_CONFIG, OPENSHIFT_PRIORITY,
- userSpecifiedDeploymentTargets.contains(OPENSHIFT)));
-
- deploymentTargets.produce(new KubernetesDeploymentTargetBuildItem(KNATIVE, SERVICE, KNATIVE_PRIORITY,
- userSpecifiedDeploymentTargets.contains(KNATIVE)));
-
- deploymentTargets.produce(
- new KubernetesDeploymentTargetBuildItem(KUBERNETES, DEPLOYMENT, VANILLA_KUBERNETES_PRIORITY,
- userSpecifiedDeploymentTargets.contains(KUBERNETES)));
- }
-
@BuildStep
public EnabledKubernetesDeploymentTargetsBuildItem enabledKubernetesDeploymentTargets(
List allDeploymentTargets) {
@@ -206,69 +74,6 @@ public EnabledKubernetesDeploymentTargetsBuildItem enabledKubernetesDeploymentTa
return new EnabledKubernetesDeploymentTargetsBuildItem(entries);
}
- @BuildStep
- public List createAnnotations(KubernetesConfig kubernetesConfig,
- OpenshiftConfig openshiftConfig, KnativeConfig knativeConfig,
- Optional metricsConfiguration, List kubernetesPorts) {
- List result = new ArrayList();
- addAnnotations(kubernetesConfig, KUBERNETES, metricsConfiguration, kubernetesPorts, result);
- addAnnotations(kubernetesConfig, MINIKUBE, metricsConfiguration, kubernetesPorts, result);
- addAnnotations(openshiftConfig, OPENSHIFT, metricsConfiguration, kubernetesPorts, result);
- addAnnotations(knativeConfig, KNATIVE, metricsConfiguration, kubernetesPorts, result);
- return result;
- }
-
- private void addAnnotations(PlatformConfiguration config, String target,
- Optional metricsConfigurationBuildItem,
- List kubernetesPorts,
- List result) {
- for (Map.Entry entry : config.getAnnotations().entrySet()) {
- result.add(new KubernetesAnnotationBuildItem(entry.getKey(), entry.getValue(), target));
- }
- if (metricsConfigurationBuildItem.isPresent() && !kubernetesPorts.isEmpty()) {
- String path = metricsConfigurationBuildItem.get().metricsEndpoint();
- if (path != null) {
- result.add(new KubernetesAnnotationBuildItem(Prometheus.SCRAPE, "true", target));
- result.add(new KubernetesAnnotationBuildItem(Prometheus.PATH, path, target));
- result.add(new KubernetesAnnotationBuildItem(Prometheus.PORT, "" + kubernetesPorts.get(0).getPort(), target));
- }
- }
- }
-
- @BuildStep
- public void createLabels(KubernetesConfig kubernetesConfig, OpenshiftConfig openshiftConfig,
- KnativeConfig knativeConfig,
- BuildProducer kubernetesLabelsProducer,
- BuildProducer containerImageLabelsProducer) {
- kubernetesConfig.labels.forEach((k, v) -> {
- kubernetesLabelsProducer.produce(new KubernetesLabelBuildItem(k, v, KUBERNETES));
- kubernetesLabelsProducer.produce(new KubernetesLabelBuildItem(k, v, MINIKUBE));
- containerImageLabelsProducer.produce(new ContainerImageLabelBuildItem(k, v));
- });
- openshiftConfig.labels.forEach((k, v) -> {
- kubernetesLabelsProducer.produce(new KubernetesLabelBuildItem(k, v, OPENSHIFT));
- containerImageLabelsProducer.produce(new ContainerImageLabelBuildItem(k, v));
- });
- knativeConfig.labels.forEach((k, v) -> {
- kubernetesLabelsProducer.produce(new KubernetesLabelBuildItem(k, v, KNATIVE));
- containerImageLabelsProducer.produce(new ContainerImageLabelBuildItem(k, v));
- });
- }
-
- @BuildStep
- public List createEnv(KubernetesConfig kubernetesConfig, OpenshiftConfig openshiftConfig,
- KnativeConfig knativeConfig) {
-
- Collection kubernetesEnvBuildItems = kubernetesConfig.convertToBuildItems();
- List items = new ArrayList<>(kubernetesEnvBuildItems);
- for (KubernetesEnvBuildItem kubernetesEnvBuildItem : kubernetesEnvBuildItems) {
- items.add(kubernetesEnvBuildItem.newWithTarget(MINIKUBE));
- }
- items.addAll(openshiftConfig.convertToBuildItems());
- items.addAll(knativeConfig.convertToBuildItems());
- return items;
- }
-
@BuildStep
public void build(ApplicationInfoBuildItem applicationInfo,
OutputTargetBuildItem outputTarget,
@@ -278,21 +83,14 @@ public void build(ApplicationInfoBuildItem applicationInfo,
KnativeConfig knativeConfig,
Capabilities capabilities,
LaunchModeBuildItem launchMode,
- List kubernetesAnnotations,
- List kubernetesLabels,
- List kubernetesEnvs,
- List kubernetesRoles,
- List kubernetesRoleBindings,
List kubernetesPorts,
EnabledKubernetesDeploymentTargetsBuildItem kubernetesDeploymentTargets,
+ List configurators,
List decorators,
- Optional baseImage,
- Optional containerImage,
- Optional command,
- Optional kubernetesHealthLivenessPath,
- Optional kubernetesHealthReadinessPath,
BuildProducer generatedResourceProducer) {
+ List allConfigurators = new ArrayList<>(configurators);
+ List allDecorators = new ArrayList<>(decorators);
if (launchMode.getLaunchMode() == LaunchMode.TEST) {
return;
}
@@ -314,13 +112,13 @@ public void build(ApplicationInfoBuildItem applicationInfo,
.map(DeploymentTargetEntry::getName)
.collect(Collectors.toSet());
- Path artifactPath = outputTarget.getOutputDirectory().resolve(
- String.format(OUTPUT_ARTIFACT_FORMAT, outputTarget.getBaseName(), packageConfig.runnerSuffix));
+ Path artifactPath = outputTarget.getOutputDirectory()
+ .resolve(String.format(OUTPUT_ARTIFACT_FORMAT, outputTarget.getBaseName(), packageConfig.runnerSuffix));
try {
final Map generatedResourcesMap;
// by passing false to SimpleFileWriter, we ensure that no files are actually written during this phase
- Project project = createProject(applicationInfo, artifactPath);
+ Project project = KubernetesCommonHelper.createProject(applicationInfo, artifactPath);
final SessionWriter sessionWriter = new SimpleFileWriter(project, false);
final SessionReader sessionReader = new SimpleFileReader(
project.getRoot().resolve("src").resolve("main").resolve("kubernetes"), kubernetesDeploymentTargets
@@ -340,53 +138,16 @@ public void build(ApplicationInfoBuildItem applicationInfo,
session.feed(Maps.fromProperties(config));
- //Apply configuration
- applyGlobalConfig(session, kubernetesConfig);
-
- ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
-
- boolean needToForceUpdateImagePullPolicy = needToForceUpdateImagePullPolicy(deploymentTargets, containerImage,
- capabilities);
- applyConfig(session, project, KUBERNETES, getResourceName(kubernetesConfig, applicationInfo), kubernetesConfig,
- now, determineImagePullPolicy(kubernetesConfig, needToForceUpdateImagePullPolicy));
- applyConfig(session, project, MINIKUBE, getResourceName(kubernetesConfig, applicationInfo), kubernetesConfig,
- now, ImagePullPolicy.IfNotPresent);
- applyConfig(session, project, OPENSHIFT, getResourceName(openshiftConfig, applicationInfo), openshiftConfig, now,
- determineImagePullPolicy(openshiftConfig, needToForceUpdateImagePullPolicy));
- applyConfig(session, project, KNATIVE, getResourceName(knativeConfig, applicationInfo), knativeConfig, now,
- determineImagePullPolicy(knativeConfig, needToForceUpdateImagePullPolicy));
-
- applyVanillaKubernetesSpecificConfig(session, kubernetesConfig);
- applyOpenshiftSpecificConfig(session, openshiftConfig);
- applyKnativeSpecificConfig(session, getResourceName(knativeConfig, applicationInfo), knativeConfig);
-
- if (!capabilities.isCapabilityPresent(Capabilities.CONTAINER_IMAGE_S2I)
- && !capabilities.isCapabilityPresent(Capabilities.CONTAINER_IMAGE_OPENSHIFT)) {
- handleNonS2IOpenshift(containerImage, session);
- }
-
- //apply build item configurations to the dekorate session.
- applyBuildItems(session,
- applicationInfo,
- kubernetesConfig,
- openshiftConfig,
- knativeConfig,
- deploymentTargets,
- kubernetesAnnotations,
- kubernetesLabels,
- kubernetesEnvs,
- kubernetesRoles,
- kubernetesRoleBindings,
- kubernetesPorts,
- baseImage,
- containerImage,
- command,
- kubernetesHealthLivenessPath,
- kubernetesHealthReadinessPath);
+ //We need to verify to filter out anything that doesn't extend the Configurator class.
+ //The ConfiguratorBuildItem is a wrapper to Object.
+ allConfigurators.stream().filter(d -> d.matches(Configurator.class)).forEach(i -> {
+ Configurator configurator = (Configurator) i.getConfigurator();
+ session.configurators().add(configurator);
+ });
//We need to verify to filter out anything that doesn't extend the Decorator class.
//The DecoratorBuildItem is a wrapper to Object.
- decorators.stream().filter(d -> d.matches(Decorator.class)).forEach(i -> {
+ allDecorators.stream().filter(d -> d.matches(Decorator.class)).forEach(i -> {
String group = i.getGroup();
Decorator decorator = (Decorator) i.getDecorator();
if (Strings.isNullOrEmpty(group)) {
@@ -398,7 +159,6 @@ public void build(ApplicationInfoBuildItem applicationInfo,
// write the generated resources to the filesystem
generatedResourcesMap = session.close();
-
List generatedFileNames = new ArrayList<>(generatedResourcesMap.size());
for (Map.Entry resourceEntry : generatedResourcesMap.entrySet()) {
Path path = Paths.get(resourceEntry.getKey());
@@ -446,543 +206,4 @@ public void build(ApplicationInfoBuildItem applicationInfo,
log.warn("Failed to generate Kubernetes resources", e);
}
}
-
- private void handleNonS2IOpenshift(Optional containerImage, Session session) {
- //When S2i is disabled we need to pass that information to dekorate.
- //Also we need to make sure that the alternatives (instances of ImageConfiguration)
- //are properly configured.
- session.configurators().add(new Configurator>() {
- @Override
- public void visit(ImageConfigurationFluent> image) {
- containerImage.ifPresent(i -> {
- String group = ImageUtil.getRepository(i.getImage()).split("/")[0];
- image.withGroup(group);
- i.getRegistry().ifPresent(r -> {
- image.withRegistry(r);
- });
- });
- }
- });
-
- session.configurators().add(new Configurator>() {
- @Override
- public void visit(S2iBuildConfigFluent> s2i) {
- s2i.withEnabled(false);
- }
- });
-
- // remove the ImageChange trigger of the DeploymentConfig
- session.resources().decorate(OPENSHIFT, new RemoveDeploymentTriggerDecorator());
- }
-
- /**
- * Apply global changes
- *
- * @param session The session to apply the changes
- * @param config The {@link KubernetesConfig} instance
- */
- private void applyGlobalConfig(Session session, KubernetesConfig config) {
- //Ports
- config.ports.entrySet().forEach(e -> session.configurators().add(new AddPort(PortConverter.convert(e))));
- }
-
- /**
- * Apply changes to the target resource group
- *
- * @param session The session to apply the changes
- * @param target The deployment target (e.g. kubernetes, openshift, knative)
- * @param name The name of the resource to accept the configuration
- * @param config The {@link PlatformConfiguration} instance
- * @param now ZonedDateTime indicating the current time
- * @param imagePullPolicy Kubernetes ImagePullPolicy to be used
- */
- private void applyConfig(Session session, Project project, String target, String name, PlatformConfiguration config,
- ZonedDateTime now, ImagePullPolicy imagePullPolicy) {
-
- if (config.getNamespace().isPresent()) {
- session.resources().decorate(target, new AddNamespaceDecorator(config.getNamespace().get()));
- }
-
- applyAnnotations(session, project, target, config, now);
-
- config.getWorkingDir().ifPresent(w -> {
- session.resources().decorate(target, new ApplyWorkingDirDecorator(name, w));
- });
-
- config.getCommand().ifPresent(c -> {
- session.resources().decorate(target, new ApplyCommandDecorator(name, c.toArray(new String[0])));
- });
-
- config.getArguments().ifPresent(a -> {
- session.resources().decorate(target, new ApplyArgsDecorator(name, a.toArray(new String[0])));
- });
-
- config.getServiceAccount().ifPresent(s -> {
- session.resources().decorate(target, new ApplyServiceAccountNamedDecorator(name, s));
- });
-
- //Image Pull
- session.resources().decorate(target, new ApplyImagePullPolicyDecorator(imagePullPolicy));
- config.getImagePullSecrets().ifPresent(l -> {
- l.forEach(s -> session.resources().decorate(target, new AddImagePullSecretDecorator(name, s)));
- });
-
- // Mounts and Volumes
- config.getMounts().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddMountDecorator(MountConverter.convert(e)));
- });
-
- config.getSecretVolumes().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddSecretVolumeDecorator(SecretVolumeConverter.convert(e)));
- });
-
- config.getConfigMapVolumes().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddConfigMapVolumeDecorator(ConfigMapVolumeConverter.convert(e)));
- });
-
- config.getPvcVolumes().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddPvcVolumeDecorator(PvcVolumeConverter.convert(e)));
- });
-
- config.getAwsElasticBlockStoreVolumes().entrySet().forEach(e -> {
- session.resources().decorate(target,
- new AddAwsElasticBlockStoreVolumeDecorator(AwsElasticBlockStoreVolumeConverter.convert(e)));
- });
-
- config.getAzureFileVolumes().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddAzureFileVolumeDecorator(AzureFileVolumeConverter.convert(e)));
- });
-
- config.getAzureDiskVolumes().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddAzureDiskVolumeDecorator(AzureDiskVolumeConverter.convert(e)));
- });
-
- config.getInitContainers().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddInitContainerDecorator(name, ContainerConverter.convert(e)));
- });
-
- config.getSidecars().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddSidecarDecorator(name, ContainerConverter.convert(e)));
- });
-
- config.getHostAliases().entrySet().forEach(e -> {
- session.resources().decorate(target, new AddHostAliasesDecorator(name, HostAliasConverter.convert(e)));
- });
-
- // The presence of optional is causing issues in OCP 3.11, so we better remove them.
- // The following 4 decorator will set the optional property to null, so that it won't make it into the file.
- session.resources().decorate(target, new RemoveOptionalFromSecretEnvSourceDecorator());
- session.resources().decorate(target, new RemoveOptionalFromConfigMapEnvSourceDecorator());
- session.resources().decorate(target, new RemoveOptionalFromSecretKeySelectorDecorator());
- session.resources().decorate(target, new RemoveOptionalFromConfigMapKeySelectorDecorator());
- }
-
- private void applyAnnotations(Session session, Project project, String target, PlatformConfiguration config,
- ZonedDateTime now) {
- ScmInfo scm = project.getScmInfo();
- String vcsUrl = scm != null ? scm.getUrl() : null;
- String commitId = scm != null ? scm.getCommit() : null;
-
- //Dekorate uses its own annotations. Let's replace them with the quarkus ones.
- session.resources().decorate(target, new RemoveAnnotationDecorator(Annotations.VCS_URL));
- session.resources().decorate(target, new RemoveAnnotationDecorator(Annotations.COMMIT_ID));
- //Add quarkus vcs annotations
- if (commitId != null) {
- session.resources().decorate(target,
- new AddAnnotationDecorator(new Annotation(QUARKUS_ANNOTATIONS_COMMIT_ID, commitId)));
- }
- if (vcsUrl != null) {
- session.resources().decorate(target,
- new AddAnnotationDecorator(new Annotation(QUARKUS_ANNOTATIONS_VCS_URL, vcsUrl)));
- }
-
- if (config.isAddBuildTimestamp()) {
- session.resources().decorate(target, new AddAnnotationDecorator(new Annotation(QUARKUS_ANNOTATIONS_BUILD_TIMESTAMP,
- now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd - HH:mm:ss Z")))));
- }
- }
-
- // apply Openshift specific configuration
- private void applyVanillaKubernetesSpecificConfig(Session session, KubernetesConfig kubernetesConfig) {
- if (!kubernetesConfig.addVersionToLabelSelectors) {
- session.resources().decorate(KUBERNETES, new RemoveLabelDecorator(Labels.VERSION));
- session.resources().decorate(KUBERNETES, new RemoveFromSelectorDecorator(Labels.VERSION));
- session.resources().decorate(KUBERNETES, new RemoveFromMatchingLabelsDecorator(Labels.VERSION));
- }
- }
-
- // apply Openshift specific configuration
- private void applyOpenshiftSpecificConfig(Session session, OpenshiftConfig openshiftConfig) {
- session.resources().decorate(OPENSHIFT, new AddLabelDecorator(new Label(OPENSHIFT_APP_RUNTIME, QUARKUS)));
-
- if (!openshiftConfig.addVersionToLabelSelectors) {
- session.resources().decorate(OPENSHIFT, new RemoveLabelDecorator(Labels.VERSION));
- session.resources().decorate(OPENSHIFT, new RemoveFromSelectorDecorator(Labels.VERSION));
- }
- }
-
- // apply Knative specific configuration
- private void applyKnativeSpecificConfig(Session session, String name, KnativeConfig config) {
- if (config.clusterLocal) {
- session.resources().decorate(KNATIVE, new AddLabelDecorator(name,
- new LabelBuilder()
- .withKey("serving.knative.dev/visibility")
- .withValue("cluster-local")
- .build()));
- }
-
- config.minScale.ifPresent(min -> session.resources().decorate(KNATIVE, new ApplyMinScaleDecorator(name, min)));
-
- config.maxScale.ifPresent(max -> session.resources().decorate(KNATIVE, new ApplyMaxScaleDecorator(name, max)));
-
- config.revisionAutoScaling.autoScalerClass.map(AutoScalerClassConverter::convert)
- .ifPresent(a -> session.resources().decorate(KNATIVE, new ApplyLocalAutoscalingClassDecorator(name, a)));
-
- config.revisionAutoScaling.metric.map(AutoScalingMetricConverter::convert)
- .ifPresent(m -> session.resources().decorate(KNATIVE, new ApplyLocalAutoscalingMetricDecorator(name, m)));
-
- config.revisionAutoScaling.containerConcurrency
- .ifPresent(c -> session.resources().decorate(KNATIVE, new ApplyLocalContainerConcurrencyDecorator(name, c)));
-
- config.revisionAutoScaling.targetUtilizationPercentage
- .ifPresent(t -> session.resources().decorate(KNATIVE,
- new ApplyLocalTargetUtilizationPercentageDecorator(name, t)));
- config.revisionAutoScaling.target
- .ifPresent(t -> session.resources().decorate(KNATIVE, new ApplyLocalAutoscalingTargetDecorator(name, t)));
-
- config.globalAutoScaling.autoScalerClass
- .map(AutoScalerClassConverter::convert)
- .ifPresent(a -> {
- session.resources().decorate(new AddConfigMapResourceProvidingDecorator("config-autoscaler"));
- session.resources().decorate(new ApplyGlobalAutoscalingClassDecorator(a));
- });
-
- config.globalAutoScaling.containerConcurrency
- .ifPresent(c -> {
- session.resources().decorate(new AddConfigMapResourceProvidingDecorator("config-defaults"));
- session.resources().decorate(new ApplyGlobalContainerConcurrencyDecorator(c));
- });
-
- config.globalAutoScaling.requestsPerSecond
- .ifPresent(r -> {
- session.resources().decorate(new AddConfigMapResourceProvidingDecorator("config-autoscaler"));
- session.resources().decorate(new ApplyGlobalRequestsPerSecondTargetDecorator(r));
- });
-
- config.globalAutoScaling.targetUtilizationPercentage
- .ifPresent(t -> {
- session.resources().decorate(new AddConfigMapResourceProvidingDecorator("config-autoscaler"));
- session.resources().decorate(new ApplyGlobalTargetUtilizationDecorator(t));
- });
-
- if (!config.scaleToZeroEnabled) {
- session.resources().decorate(new AddConfigMapResourceProvidingDecorator("config-autoscaler"));
- session.resources().decorate(new AddConfigMapDataDecorator("config-autoscaler", "enable-scale-to-zero",
- String.valueOf(config.scaleToZeroEnabled)));
- }
- }
-
- /**
- * When there is no registry defined and s2i isn't being used, the only ImagePullPolicy that can work is 'IfNotPresent'.
- * This case comes up when users want to deploy their application to a cluster like Minikube where no registry is used
- * and instead they rely on the image being built directly into the docker daemon that the cluster uses.
- */
- private boolean needToForceUpdateImagePullPolicy(Collection deploymentTargets,
- Optional containerImage,
- Capabilities capabilities) {
-
- // no need to change when we use Minikube only
- if ((deploymentTargets.size() == 1) && deploymentTargets.contains(MINIKUBE)) {
- return false;
- }
-
- boolean result = containerImage.isPresent()
- && ContainerImageUtil.isRegistryMissingAndNotS2I(capabilities, containerImage.get());
- if (result) {
- log.warn("No registry was set for the container image, so 'ImagePullPolicy' is being force-set to 'IfNotPresent'.");
- return true;
- }
- return false;
- }
-
- private ImagePullPolicy determineImagePullPolicy(PlatformConfiguration config, boolean needToForceUpdateImagePullPolicy) {
- if (needToForceUpdateImagePullPolicy) {
- return ImagePullPolicy.IfNotPresent;
- }
- return config.getImagePullPolicy();
- }
-
- private void applyBuildItems(Session session,
- ApplicationInfoBuildItem applicationInfo,
- KubernetesConfig kubernetesConfig,
- OpenshiftConfig openshiftConfig,
- KnativeConfig knativeConfig,
- Set deploymentTargets,
- List kubernetesAnnotations,
- List kubernetesLabels,
- List kubernetesEnvs,
- List kubernetesRoles,
- List kubernetesRoleBindings,
- List kubernetesPorts,
- Optional baseImage,
- Optional containerImage,
- Optional command,
- Optional kubernetesHealthLivenessPath,
- Optional kubernetesHealthReadinessPath) {
-
- String kubernetesName = getResourceName(kubernetesConfig, applicationInfo);
- String openshiftName = getResourceName(openshiftConfig, applicationInfo);
- String knativeName = getResourceName(knativeConfig, applicationInfo);
-
- Map configMap = new HashMap<>();
- configMap.put(KUBERNETES, kubernetesConfig);
- configMap.put(MINIKUBE, kubernetesConfig);
- configMap.put(OPENSHIFT, openshiftConfig);
- configMap.put(KNATIVE, knativeConfig);
-
- //Replicas
- if (kubernetesConfig.getReplicas() != 1) {
- session.resources().decorate(new io.dekorate.kubernetes.decorator.ApplyReplicasDecorator(kubernetesName,
- kubernetesConfig.getReplicas()));
- }
- if (openshiftConfig.getReplicas() != 1) {
- session.resources()
- .decorate(new io.dekorate.openshift.decorator.ApplyReplicasDecorator(openshiftName,
- openshiftConfig.getReplicas()));
- }
-
- kubernetesAnnotations.forEach(a -> {
- session.resources().decorate(a.getTarget(), new AddAnnotationDecorator(new Annotation(a.getKey(), a.getValue())));
- });
-
- kubernetesLabels.forEach(l -> {
- session.resources().decorate(l.getTarget(), new AddLabelDecorator(new Label(l.getKey(), l.getValue())));
- });
-
- containerImage.ifPresent(c -> {
- session.resources().decorate(OPENSHIFT, new ApplyContainerImageDecorator(openshiftName, c.getImage()));
- session.resources().decorate(KUBERNETES, new ApplyContainerImageDecorator(kubernetesName, c.getImage()));
- session.resources().decorate(MINIKUBE, new ApplyContainerImageDecorator(kubernetesName, c.getImage()));
- session.resources().decorate(KNATIVE, new ApplyContainerImageDecorator(knativeName, c.getImage()));
- });
-
- kubernetesEnvs.forEach(e -> {
- String containerName = kubernetesName;
- if (e.getTarget().equals(OPENSHIFT)) {
- containerName = openshiftName;
- } else if (e.getTarget().equals(KNATIVE)) {
- containerName = knativeName;
- }
- session.resources().decorate(e.getTarget(), createAddEnvDecorator(e, containerName));
- });
-
- //Handle Command and arguments
- command.ifPresent(c -> {
- session.resources().decorate(new ApplyCommandDecorator(kubernetesName, new String[] { c.getCommand() }));
- session.resources().decorate(KUBERNETES, new ApplyArgsDecorator(kubernetesName, c.getArgs()));
- session.resources().decorate(MINIKUBE, new ApplyArgsDecorator(kubernetesName, c.getArgs()));
-
- session.resources().decorate(new ApplyCommandDecorator(openshiftName, new String[] { c.getCommand() }));
- session.resources().decorate(OPENSHIFT, new ApplyArgsDecorator(openshiftName, c.getArgs()));
-
- session.resources().decorate(new ApplyCommandDecorator(knativeName, new String[] { c.getCommand() }));
- session.resources().decorate(KNATIVE, new ApplyArgsDecorator(knativeName, c.getArgs()));
- });
-
- //Handle ports
- final Map ports = verifyPorts(kubernetesPorts);
- ports.entrySet().stream()
- .map(e -> new PortBuilder().withName(e.getKey()).withContainerPort(e.getValue()).build())
- .forEach(p -> session.configurators().add(new AddPort(p)));
-
- //Handle RBAC
- if (!kubernetesRoleBindings.isEmpty()) {
- session.resources().decorate(new ApplyServiceAccountNamedDecorator());
- session.resources().decorate(new AddServiceAccountResourceDecorator());
- kubernetesRoles.forEach(r -> session.resources().decorate(new AddRoleResourceDecorator(r)));
- kubernetesRoleBindings.forEach(rb -> session.resources().decorate(
- new AddRoleBindingResourceDecorator(rb.getName(), null, rb.getRole(),
- rb.isClusterWide()
- ? AddRoleBindingResourceDecorator.RoleKind.ClusterRole
- : AddRoleBindingResourceDecorator.RoleKind.Role)));
- }
-
- handleServices(session, kubernetesConfig, openshiftConfig, knativeConfig, kubernetesName, openshiftName, knativeName);
-
- //Handle custom s2i builder images
- if (deploymentTargets.contains(OPENSHIFT)) {
- baseImage.map(BaseImageInfoBuildItem::getImage).ifPresent(builderImage -> {
- String builderImageName = ImageUtil.getName(builderImage);
- S2iBuildConfig s2iBuildConfig = new S2iBuildConfigBuilder().withBuilderImage(builderImage).build();
- if (!DEFAULT_S2I_IMAGE_NAME.equals(builderImageName)) {
- session.resources().decorate(OPENSHIFT, new RemoveBuilderImageResourceDecorator(DEFAULT_S2I_IMAGE_NAME));
- }
- session.resources().decorate(OPENSHIFT, new AddBuilderImageStreamResourceDecorator(s2iBuildConfig));
- session.resources().decorate(OPENSHIFT, new ApplyBuilderImageDecorator(openshiftName, builderImage));
- });
- }
-
- // only use the probe config
- handleProbes(applicationInfo, kubernetesConfig, openshiftConfig, knativeConfig, deploymentTargets, ports,
- kubernetesHealthLivenessPath,
- kubernetesHealthReadinessPath, session);
- }
-
- private AddEnvVarDecorator createAddEnvDecorator(KubernetesEnvBuildItem e, String containerName) {
- return new AddEnvVarDecorator(ApplicationContainerDecorator.ANY, containerName, new EnvBuilder()
- .withName(EnvConverter.convertName(e.getName()))
- .withValue(e.getValue())
- .withSecret(e.getSecret())
- .withConfigmap(e.getConfigMap())
- .withField(e.getField())
- .build());
- }
-
- private void handleServices(Session session, KubernetesConfig kubernetesConfig, OpenshiftConfig openshiftConfig,
- KnativeConfig knativeConfig, String kubernetesName, String openshiftName, String knativeName) {
- session.resources().decorate(KUBERNETES,
- new ApplyServiceTypeDecorator(kubernetesName, kubernetesConfig.getServiceType().name()));
- if ((kubernetesConfig.getServiceType() == ServiceType.NodePort) && kubernetesConfig.nodePort.isPresent()) {
- session.resources().decorate(KUBERNETES,
- new AddNodePortDecorator(openshiftName, kubernetesConfig.nodePort.getAsInt()));
- }
- session.resources().decorate(MINIKUBE,
- new ApplyServiceTypeDecorator(kubernetesName, ServiceType.NodePort.name()));
- session.resources().decorate(MINIKUBE, new AddNodePortDecorator(kubernetesName, kubernetesConfig.nodePort
- .orElseGet(() -> getStablePortNumberInRange(kubernetesName, MIN_NODE_PORT_VALUE, MAX_NODE_PORT_VALUE))));
-
- session.resources().decorate(OPENSHIFT,
- new ApplyServiceTypeDecorator(openshiftName, openshiftConfig.getServiceType().name()));
- if ((openshiftConfig.getServiceType() == ServiceType.NodePort) && openshiftConfig.nodePort.isPresent()) {
- session.resources().decorate(OPENSHIFT,
- new AddNodePortDecorator(openshiftName, openshiftConfig.nodePort.getAsInt()));
- }
-
- session.resources().decorate(KNATIVE,
- new ApplyServiceTypeDecorator(knativeName, knativeConfig.getServiceType().name()));
- }
-
- /**
- * Given a string, generate a port number within the supplied range
- * The output is always the same (between {@code min} and {@code max})
- * given the same input and it's useful when we need to generate a port number
- * which needs to stay the same but we don't care about the exact value
- */
- private int getStablePortNumberInRange(String input, int min, int max) {
- if (min < MIN_PORT_NUMBER || max > MAX_PORT_NUMBER) {
- throw new IllegalArgumentException(
- String.format("Port number range must be within [%d-%d]", MIN_PORT_NUMBER, MAX_PORT_NUMBER));
- }
-
- try {
- byte[] hash = MessageDigest.getInstance(DEFAULT_HASH_ALGORITHM).digest(input.getBytes(StandardCharsets.UTF_8));
- return min + new BigInteger(hash).mod(BigInteger.valueOf(max - min)).intValue();
- } catch (Exception e) {
- throw new RuntimeException("Unable to generate stable port number from input string: '" + input + "'", e);
- }
- }
-
- private void handleProbes(ApplicationInfoBuildItem applicationInfo, KubernetesConfig kubernetesConfig,
- OpenshiftConfig openshiftConfig,
- KnativeConfig knativeConfig,
- Set deploymentTargets, Map ports,
- Optional kubernetesHealthLivenessPathBuildItem,
- Optional kubernetesHealthReadinessPathBuildItem,
- Session session) {
- if (deploymentTargets.contains(KUBERNETES)) {
- doHandleProbes(getResourceName(kubernetesConfig, applicationInfo), KUBERNETES, ports,
- kubernetesConfig.livenessProbe, kubernetesConfig.readinessProbe, kubernetesHealthLivenessPathBuildItem,
- kubernetesHealthReadinessPathBuildItem, session);
- }
- if (deploymentTargets.contains(MINIKUBE)) {
- doHandleProbes(getResourceName(kubernetesConfig, applicationInfo), MINIKUBE, ports,
- kubernetesConfig.livenessProbe, kubernetesConfig.readinessProbe, kubernetesHealthLivenessPathBuildItem,
- kubernetesHealthReadinessPathBuildItem, session);
- }
- if (deploymentTargets.contains(OPENSHIFT)) {
- doHandleProbes(getResourceName(kubernetesConfig, applicationInfo), OPENSHIFT, ports, openshiftConfig.livenessProbe,
- openshiftConfig.readinessProbe, kubernetesHealthLivenessPathBuildItem,
- kubernetesHealthReadinessPathBuildItem, session);
- }
- if (deploymentTargets.contains(KNATIVE)) {
- doHandleProbes(getResourceName(kubernetesConfig, applicationInfo), KNATIVE, ports, knativeConfig.livenessProbe,
- knativeConfig.readinessProbe, kubernetesHealthLivenessPathBuildItem, kubernetesHealthReadinessPathBuildItem,
- session);
- }
- }
-
- private void doHandleProbes(String name, String target, Map ports, ProbeConfig livenessProbe,
- ProbeConfig readinessProbe, Optional kubernetesHealthLivenessPathBuildItem,
- Optional kubernetesHealthReadinessPathBuildItem, Session session) {
- handleLivenessProbe(name, target, livenessProbe, kubernetesHealthLivenessPathBuildItem, session);
- handleReadinessProbe(name, target, readinessProbe, kubernetesHealthReadinessPathBuildItem,
- session);
-
- //For knative we want the port to be null
- Integer port = KNATIVE.equals(target) ? null : ports.getOrDefault(HTTP_PORT, DEFAULT_HTTP_PORT);
- session.resources().decorate(target, new ApplyHttpGetActionPortDecorator(port));
- }
-
- private void handleLivenessProbe(String name, String target, ProbeConfig livenessProbe,
- Optional kubernetesHealthLivenessPathBuildItem, Session session) {
- AddLivenessProbeDecorator livenessProbeDecorator = null;
- if (livenessProbe.hasUserSuppliedAction()) {
- livenessProbeDecorator = new AddLivenessProbeDecorator(name,
- ProbeConverter.convert(livenessProbe));
- } else if (kubernetesHealthLivenessPathBuildItem.isPresent()) {
- livenessProbeDecorator = new AddLivenessProbeDecorator(name,
- ProbeConverter.builder(livenessProbe)
- .withHttpActionPath(kubernetesHealthLivenessPathBuildItem.get().getPath()).build());
- }
- if (livenessProbeDecorator != null) {
- session.resources().decorate(target, livenessProbeDecorator);
- }
- }
-
- private void handleReadinessProbe(String name, String target, ProbeConfig readinessProbe,
- Optional healthReadinessPathBuildItem, Session session) {
- AddReadinessProbeDecorator readinessProbeDecorator = null;
- if (readinessProbe.hasUserSuppliedAction()) {
- readinessProbeDecorator = new AddReadinessProbeDecorator(name, ProbeConverter.convert(readinessProbe));
- } else if (healthReadinessPathBuildItem.isPresent()) {
- readinessProbeDecorator = new AddReadinessProbeDecorator(name, ProbeConverter.builder(readinessProbe)
- .withHttpActionPath(healthReadinessPathBuildItem.get().getPath()).build());
- }
- if (readinessProbeDecorator != null) {
- session.resources().decorate(target, readinessProbeDecorator);
- }
- }
-
- private Map verifyPorts(List kubernetesPortBuildItems) {
- final Map result = new HashMap<>();
- final Set usedPorts = new HashSet<>();
- for (KubernetesPortBuildItem entry : kubernetesPortBuildItems) {
- final String name = entry.getName();
- if (result.containsKey(name)) {
- throw new IllegalArgumentException(
- "All Kubernetes ports must have unique names - " + name + "has been used multiple times");
- }
- final Integer port = entry.getPort();
- if (usedPorts.contains(port)) {
- throw new IllegalArgumentException(
- "All Kubernetes ports must be unique - " + port + "has been used multiple times");
- }
- result.put(name, port);
- usedPorts.add(port);
- }
- return result;
- }
-
- private Project createProject(ApplicationInfoBuildItem app, Path artifactPath) {
- //Let dekorate create a Project instance and then override with what is found in ApplicationInfoBuildItem.
- Project project = FileProjectFactory.create(artifactPath.toFile());
- BuildInfo buildInfo = new BuildInfo(app.getName(), app.getVersion(),
- "jar", project.getBuildInfo().getBuildTool(),
- artifactPath.toAbsolutePath().toString(),
- artifactPath,
- project.getBuildInfo().getResourceDir());
-
- return new Project(project.getRoot(), buildInfo, project.getScmInfo());
- }
-
}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/MinikubeHandler.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/MinikubeHandler.java
index e0b56ccba9071..d2a1a8955f351 100644
--- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/MinikubeHandler.java
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/MinikubeHandler.java
@@ -1,6 +1,5 @@
package io.quarkus.kubernetes.deployment;
-import static io.dekorate.utils.Labels.createLabels;
import static io.quarkus.kubernetes.deployment.Constants.MINIKUBE;
import java.util.Optional;
@@ -125,7 +124,7 @@ protected void addDecorators(String group, KubernetesConfig config) {
resources.decorate(group, new AddServiceResourceDecorator(config));
}
- resources.decorate(group, new AddIngressDecorator(config, Labels.createLabels(config)));
+ resources.decorate(group, new AddIngressDecorator(config, Labels.createLabelsAsMap(config, "Ingress")));
resources.decorate(group, new ApplyLabelSelectorDecorator(createSelector(config)));
}
@@ -139,7 +138,7 @@ public Deployment createDeployment(KubernetesConfig appConfig, ImageConfiguratio
return new DeploymentBuilder()
.withNewMetadata()
.withName(appConfig.getName())
- .withLabels(Labels.createLabels(appConfig))
+ .withLabels(Labels.createLabelsAsMap(appConfig, "Deployment"))
.endMetadata()
.withNewSpec()
.withReplicas(1)
@@ -156,7 +155,7 @@ public Deployment createDeployment(KubernetesConfig appConfig, ImageConfiguratio
*/
public LabelSelector createSelector(KubernetesConfig config) {
return new LabelSelectorBuilder()
- .withMatchLabels(Labels.createLabels(config))
+ .withMatchLabels(Labels.createLabelsAsMap(config, "Deployment"))
.build();
}
@@ -170,7 +169,7 @@ public static PodTemplateSpec createPodTemplateSpec(KubernetesConfig appConfig,
return new PodTemplateSpecBuilder()
.withSpec(createPodSpec(appConfig, imageConfig))
.withNewMetadata()
- .withLabels(createLabels(appConfig))
+ .withLabels(Labels.createLabelsAsMap(appConfig, "Deployment"))
.endMetadata()
.build();
}
@@ -236,4 +235,5 @@ private static ImageConfiguration merge(KubernetesConfig appConfig, ImageConfigu
.withAutoPushEnabled(imageConfig.isAutoPushEnabled() ? imageConfig.isAutoPushEnabled() : false)
.build();
}
+
}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java
new file mode 100644
index 0000000000000..5c6134593ca93
--- /dev/null
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java
@@ -0,0 +1,186 @@
+
+package io.quarkus.kubernetes.deployment;
+
+import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT;
+import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_S2I_IMAGE_NAME;
+import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT;
+import static io.quarkus.kubernetes.deployment.Constants.HTTP_PORT;
+import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT;
+import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT_APP_RUNTIME;
+import static io.quarkus.kubernetes.deployment.Constants.QUARKUS;
+import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.DEFAULT_PRIORITY;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import io.dekorate.kubernetes.annotation.ServiceType;
+import io.dekorate.kubernetes.config.EnvBuilder;
+import io.dekorate.kubernetes.decorator.AddEnvVarDecorator;
+import io.dekorate.kubernetes.decorator.AddLabelDecorator;
+import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator;
+import io.dekorate.kubernetes.decorator.RemoveFromSelectorDecorator;
+import io.dekorate.kubernetes.decorator.RemoveLabelDecorator;
+import io.dekorate.openshift.decorator.ApplyReplicasDecorator;
+import io.dekorate.project.Project;
+import io.dekorate.s2i.config.S2iBuildConfig;
+import io.dekorate.s2i.config.S2iBuildConfigBuilder;
+import io.dekorate.s2i.decorator.AddBuilderImageStreamResourceDecorator;
+import io.dekorate.utils.Labels;
+import io.quarkus.container.image.deployment.util.ImageUtil;
+import io.quarkus.container.spi.BaseImageInfoBuildItem;
+import io.quarkus.container.spi.ContainerImageInfoBuildItem;
+import io.quarkus.container.spi.ContainerImageLabelBuildItem;
+import io.quarkus.deployment.Capabilities;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
+import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
+import io.quarkus.deployment.pkg.PackageConfig;
+import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
+import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
+import io.quarkus.kubernetes.spi.DecoratorBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesEnvBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;
+
+public class OpenshiftProcessor {
+
+ private static final int OPENSHIFT_PRIORITY = DEFAULT_PRIORITY;
+
+ @BuildStep
+ public void checkOpenshift(BuildProducer deploymentTargets) {
+ List targets = KubernetesConfigUtil.getUserSpecifiedDeploymentTargets();
+ deploymentTargets.produce(new KubernetesDeploymentTargetBuildItem(OPENSHIFT, DEPLOYMENT, OPENSHIFT_PRIORITY,
+ targets.contains(OPENSHIFT)));
+ }
+
+ @BuildStep
+ public void createAnnotations(OpenshiftConfig config, BuildProducer annotations) {
+ config.getAnnotations().forEach((k, v) -> {
+ annotations.produce(new KubernetesAnnotationBuildItem(k, v, OPENSHIFT));
+ });
+ }
+
+ @BuildStep
+ public void createLabels(OpenshiftConfig config, BuildProducer labels,
+ BuildProducer imageLabels) {
+ config.getLabels().forEach((k, v) -> {
+ labels.produce(new KubernetesLabelBuildItem(k, v, OPENSHIFT));
+ imageLabels.produce(new ContainerImageLabelBuildItem(k, v));
+ });
+ }
+
+ @BuildStep
+ public List createConfigurators(ApplicationInfoBuildItem applicationInfo,
+ OpenshiftConfig config, Capabilities capabilities, Optional image,
+ List ports) {
+
+ List result = new ArrayList<>();
+ result.addAll(KubernetesCommonHelper.createPlatformConfigurators(config));
+ result.addAll(KubernetesCommonHelper.createGlobalConfigurators(ports));
+
+ if (!capabilities.isCapabilityPresent(Capabilities.CONTAINER_IMAGE_S2I)
+ && !capabilities.isCapabilityPresent(Capabilities.CONTAINER_IMAGE_OPENSHIFT)) {
+ result.add(new ConfiguratorBuildItem(new DisableS2iConfigurator()));
+
+ image.flatMap(ContainerImageInfoBuildItem::getRegistry).ifPresent(r -> {
+ result.add(new ConfiguratorBuildItem(new ApplyImageRegistryConfigurator(r)));
+ });
+
+ image.map(ContainerImageInfoBuildItem::getGroup).ifPresent(g -> {
+ result.add(new ConfiguratorBuildItem(new ApplyImageGroupConfigurator(g)));
+ });
+ }
+ return result;
+ }
+
+ @BuildStep
+ public List createDecorators(ApplicationInfoBuildItem applicationInfo,
+ OutputTargetBuildItem outputTarget,
+ OpenshiftConfig config,
+ PackageConfig packageConfig,
+ Optional metricsConfiguration,
+ Capabilities capabilities,
+ List annotations,
+ List labels,
+ List envs,
+ Optional baseImage,
+ Optional image,
+ Optional command,
+ List ports,
+ Optional livenessPath,
+ Optional readinessPath,
+ List roles,
+ List roleBindings) {
+
+ List result = new ArrayList<>();
+ String name = ResourceNameUtil.getResourceName(config, applicationInfo);
+
+ Project project = KubernetesCommonHelper.createProject(applicationInfo, outputTarget, packageConfig);
+ result.addAll(KubernetesCommonHelper.createDecorators(project, OPENSHIFT, name, config, metricsConfiguration,
+ annotations, labels, command,
+ ports, livenessPath, readinessPath, roles, roleBindings));
+
+ if (config.getReplicas() != 1) {
+ result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyReplicasDecorator(name, config.getReplicas())));
+ }
+ image.ifPresent(i -> {
+ result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyContainerImageDecorator(name, i.getImage())));
+ });
+ result.add(new DecoratorBuildItem(OPENSHIFT, new AddLabelDecorator(name, OPENSHIFT_APP_RUNTIME, QUARKUS)));
+
+ Stream.concat(config.convertToBuildItems().stream(),
+ envs.stream().filter(e -> e.getTarget() == null || OPENSHIFT.equals(e.getTarget()))).forEach(e -> {
+ result.add(new DecoratorBuildItem(OPENSHIFT,
+ new AddEnvVarDecorator(ApplicationContainerDecorator.ANY, name,
+ new EnvBuilder().withName(EnvConverter.convertName(e.getName())).withValue(e.getValue())
+ .withSecret(e.getSecret()).withConfigmap(e.getConfigMap()).withField(e.getField())
+ .build())));
+ });
+
+ // Handle custom s2i builder images
+ baseImage.map(BaseImageInfoBuildItem::getImage).ifPresent(builderImage -> {
+ String builderImageName = ImageUtil.getName(builderImage);
+ S2iBuildConfig s2iBuildConfig = new S2iBuildConfigBuilder().withBuilderImage(builderImage).build();
+ if (!DEFAULT_S2I_IMAGE_NAME.equals(builderImageName)) {
+ result.add(new DecoratorBuildItem(OPENSHIFT, new RemoveBuilderImageResourceDecorator(DEFAULT_S2I_IMAGE_NAME)));
+ }
+ result.add(new DecoratorBuildItem(OPENSHIFT, new AddBuilderImageStreamResourceDecorator(s2iBuildConfig)));
+ result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyBuilderImageDecorator(name, builderImage)));
+ });
+
+ if (!config.addVersionToLabelSelectors) {
+ result.add(new DecoratorBuildItem(OPENSHIFT, new RemoveLabelDecorator(name, Labels.VERSION)));
+ result.add(new DecoratorBuildItem(OPENSHIFT, new RemoveFromSelectorDecorator(name, Labels.VERSION)));
+ }
+
+ // Service handling
+ result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyServiceTypeDecorator(name, config.getServiceType().name())));
+ if ((config.getServiceType() == ServiceType.NodePort) && config.nodePort.isPresent()) {
+ result.add(new DecoratorBuildItem(OPENSHIFT, new AddNodePortDecorator(name, config.nodePort.getAsInt())));
+ }
+
+ // Probe port handling
+ Integer port = ports.stream().filter(p -> HTTP_PORT.equals(p.getName())).map(KubernetesPortBuildItem::getPort)
+ .findFirst().orElse(DEFAULT_HTTP_PORT);
+ result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyHttpGetActionPortDecorator(port)));
+
+ // Hanlde non-s2i
+ if (!capabilities.isCapabilityPresent(Capabilities.CONTAINER_IMAGE_S2I)
+ && !capabilities.isCapabilityPresent(Capabilities.CONTAINER_IMAGE_OPENSHIFT)) {
+ result.add(new DecoratorBuildItem(OPENSHIFT, new RemoveDeploymentTriggerDecorator()));
+ }
+
+ return result;
+ }
+
+}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ResourceNameUtil.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ResourceNameUtil.java
index e3479cfbef334..afd565d71b3ff 100644
--- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ResourceNameUtil.java
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ResourceNameUtil.java
@@ -2,7 +2,7 @@
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
-final class ResourceNameUtil {
+public final class ResourceNameUtil {
private ResourceNameUtil() {
}
@@ -12,7 +12,8 @@ private ResourceNameUtil() {
* Uses the value from the configuration object if it exists, otherwise falls back to
* the application name
*/
- static String getResourceName(PlatformConfiguration platformConfiguration, ApplicationInfoBuildItem applicationInfo) {
+ public static String getResourceName(PlatformConfiguration platformConfiguration,
+ ApplicationInfoBuildItem applicationInfo) {
return platformConfiguration.getName().orElse(applicationInfo.getName());
}
}
diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java
new file mode 100644
index 0000000000000..5499631b073e1
--- /dev/null
+++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java
@@ -0,0 +1,146 @@
+
+package io.quarkus.kubernetes.deployment;
+
+import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT;
+import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT;
+import static io.quarkus.kubernetes.deployment.Constants.HTTP_PORT;
+import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES;
+import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.VANILLA_KUBERNETES_PRIORITY;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import io.dekorate.kubernetes.annotation.ServiceType;
+import io.dekorate.kubernetes.config.EnvBuilder;
+import io.dekorate.kubernetes.decorator.AddEnvVarDecorator;
+import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator;
+import io.dekorate.kubernetes.decorator.ApplyImagePullPolicyDecorator;
+import io.dekorate.kubernetes.decorator.ApplyReplicasDecorator;
+import io.dekorate.kubernetes.decorator.RemoveFromMatchingLabelsDecorator;
+import io.dekorate.kubernetes.decorator.RemoveFromSelectorDecorator;
+import io.dekorate.kubernetes.decorator.RemoveLabelDecorator;
+import io.dekorate.project.Project;
+import io.dekorate.utils.Labels;
+import io.quarkus.container.spi.ContainerImageInfoBuildItem;
+import io.quarkus.container.spi.ContainerImageLabelBuildItem;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
+import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
+import io.quarkus.deployment.pkg.PackageConfig;
+import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
+import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
+import io.quarkus.kubernetes.spi.DecoratorBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesEnvBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
+import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;
+
+public class VanillaKubernetesProcessor {
+
+ @BuildStep
+ public void checkVanillaKubernetes(BuildProducer deploymentTargets) {
+ List userSpecifiedDeploymentTargets = KubernetesConfigUtil.getUserSpecifiedDeploymentTargets();
+ if (userSpecifiedDeploymentTargets.isEmpty()) {
+ // when nothing was selected by the user, we enable vanilla Kubernetes by
+ // default
+ deploymentTargets
+ .produce(
+ new KubernetesDeploymentTargetBuildItem(KUBERNETES, DEPLOYMENT, VANILLA_KUBERNETES_PRIORITY, true));
+ }
+
+ deploymentTargets.produce(new KubernetesDeploymentTargetBuildItem(KUBERNETES, DEPLOYMENT,
+ VANILLA_KUBERNETES_PRIORITY, userSpecifiedDeploymentTargets.contains(KUBERNETES)));
+ }
+
+ @BuildStep
+ public void createAnnotations(KubernetesConfig config, BuildProducer annotations) {
+ config.annotations.forEach((k, v) -> {
+ annotations.produce(new KubernetesAnnotationBuildItem(k, v, KUBERNETES));
+ });
+ }
+
+ @BuildStep
+ public void createLabels(KubernetesConfig config, BuildProducer labels,
+ BuildProducer imageLabels) {
+ config.labels.forEach((k, v) -> {
+ labels.produce(new KubernetesLabelBuildItem(k, v, KUBERNETES));
+ imageLabels.produce(new ContainerImageLabelBuildItem(k, v));
+ });
+ }
+
+ @BuildStep
+ public List createConfigurators(KubernetesConfig config, List ports) {
+ List result = new ArrayList<>();
+ result.addAll(KubernetesCommonHelper.createPlatformConfigurators(config));
+ result.addAll(KubernetesCommonHelper.createGlobalConfigurators(ports));
+ return result;
+
+ }
+
+ @BuildStep
+ public List createDecorators(ApplicationInfoBuildItem applicationInfo,
+ OutputTargetBuildItem outputTarget, KubernetesConfig config, PackageConfig packageConfig,
+ Optional metricsConfiguration, List annotations,
+ List labels, List envs,
+ Optional image, Optional command,
+ List ports, Optional livenessPath,
+ Optional readinessPath, List roles,
+ List roleBindings) {
+
+ final List result = new ArrayList<>();
+ final String name = ResourceNameUtil.getResourceName(config, applicationInfo);
+
+ Project project = KubernetesCommonHelper.createProject(applicationInfo, outputTarget, packageConfig);
+ result.addAll(KubernetesCommonHelper.createDecorators(project, KUBERNETES, name, config, metricsConfiguration,
+ annotations, labels, command, ports, livenessPath, readinessPath, roles, roleBindings));
+
+ if (config.getReplicas() != 1) {
+ result.add(new DecoratorBuildItem(KUBERNETES, new ApplyReplicasDecorator(name, config.getReplicas())));
+ }
+
+ image.ifPresent(i -> {
+ result.add(new DecoratorBuildItem(KUBERNETES, new ApplyContainerImageDecorator(name, i.getImage())));
+ });
+
+ result
+ .add(new DecoratorBuildItem(KUBERNETES, new ApplyImagePullPolicyDecorator(name, config.getImagePullPolicy())));
+
+ Stream.concat(config.convertToBuildItems().stream(),
+ envs.stream().filter(e -> e.getTarget() == null || KUBERNETES.equals(e.getTarget()))).forEach(e -> {
+ result.add(new DecoratorBuildItem(KUBERNETES,
+ new AddEnvVarDecorator(ApplicationContainerDecorator.ANY, name,
+ new EnvBuilder().withName(EnvConverter.convertName(e.getName())).withValue(e.getValue())
+ .withSecret(e.getSecret()).withConfigmap(e.getConfigMap()).withField(e.getField())
+ .build())));
+ });
+
+ if (!config.addVersionToLabelSelectors) {
+ result.add(new DecoratorBuildItem(KUBERNETES, new RemoveLabelDecorator(name, Labels.VERSION)));
+ result.add(new DecoratorBuildItem(KUBERNETES, new RemoveFromSelectorDecorator(name, Labels.VERSION)));
+ result.add(new DecoratorBuildItem(KUBERNETES, new RemoveFromMatchingLabelsDecorator(name, Labels.VERSION)));
+ }
+
+ // Service handling
+ result.add(new DecoratorBuildItem(KUBERNETES, new ApplyServiceTypeDecorator(name, config.getServiceType().name())));
+ if ((config.getServiceType() == ServiceType.NodePort) && config.nodePort.isPresent()) {
+ result.add(new DecoratorBuildItem(KUBERNETES, new AddNodePortDecorator(name, config.nodePort.getAsInt())));
+ }
+
+ // Probe port handling
+ Integer port = ports.stream().filter(p -> HTTP_PORT.equals(p.getName())).map(KubernetesPortBuildItem::getPort)
+ .findFirst().orElse(DEFAULT_HTTP_PORT);
+ result.add(new DecoratorBuildItem(KUBERNETES, new ApplyHttpGetActionPortDecorator(port)));
+
+ return result;
+ }
+
+}
diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesAndMinikubeWithApplicationPropertiesTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesAndMinikubeWithApplicationPropertiesTest.java
index 7fbbca5a79594..819e2419d754d 100644
--- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesAndMinikubeWithApplicationPropertiesTest.java
+++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesAndMinikubeWithApplicationPropertiesTest.java
@@ -31,8 +31,7 @@ public class KubernetesAndMinikubeWithApplicationPropertiesTest {
.setApplicationVersion("0.1-SNAPSHOT")
.withConfigurationResource("kubernetes-and-minikube-with-application.properties")
.setForcedDependencies(
- Collections.singletonList(
- new AppArtifact("io.quarkus", "quarkus-minikube", Version.getVersion())));
+ Collections.singletonList(new AppArtifact("io.quarkus", "quarkus-minikube", Version.getVersion())));
@ProdBuildResults
private ProdModeTestResults prodModeTestResults;
diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthAndJibTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthAndJibTest.java
index 5049899538498..280350cf0dbe1 100644
--- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthAndJibTest.java
+++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthAndJibTest.java
@@ -62,8 +62,7 @@ public void assertGeneratedResources() throws IOException {
assertThat(container.getLivenessProbe()).isNotNull().satisfies(p -> {
assertProbePath(p, "/health/live");
});
- // since no registry was set and a container-image extension exists, we force-set 'IfNotPresent'
- assertThat(container.getImagePullPolicy()).isEqualTo("IfNotPresent");
+ assertThat(container.getImagePullPolicy()).isEqualTo("Always");
});
});
});
diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithApplicationPropertiesTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithApplicationPropertiesTest.java
index c43ed5132c57b..728e0d4844061 100644
--- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithApplicationPropertiesTest.java
+++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithApplicationPropertiesTest.java
@@ -6,6 +6,7 @@
import java.io.IOException;
import java.nio.file.Path;
+import java.util.Collections;
import java.util.List;
import org.jboss.shrinkwrap.api.ShrinkWrap;
@@ -16,6 +17,8 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.quarkus.bootstrap.model.AppArtifact;
+import io.quarkus.builder.Version;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;
@@ -27,7 +30,9 @@ public class MinikubeWithApplicationPropertiesTest {
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(GreetingResource.class))
.setApplicationName("minikube-with-application-properties")
.setApplicationVersion("0.1-SNAPSHOT")
- .withConfigurationResource("minikube-with-application.properties");
+ .withConfigurationResource("minikube-with-application.properties")
+ .setForcedDependencies(
+ Collections.singletonList(new AppArtifact("io.quarkus", "quarkus-minikube", Version.getVersion())));
@ProdBuildResults
private ProdModeTestResults prodModeTestResults;
diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithDefaultsTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithDefaultsTest.java
index afe4837ca8007..4b027bf0f3786 100644
--- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithDefaultsTest.java
+++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithDefaultsTest.java
@@ -5,6 +5,7 @@
import java.io.IOException;
import java.nio.file.Path;
+import java.util.Collections;
import java.util.List;
import org.jboss.shrinkwrap.api.ShrinkWrap;
@@ -15,6 +16,8 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.quarkus.bootstrap.model.AppArtifact;
+import io.quarkus.builder.Version;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;
@@ -26,7 +29,9 @@ public class MinikubeWithDefaultsTest {
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(GreetingResource.class))
.setApplicationName("minikube-with-defaults")
.setApplicationVersion("0.1-SNAPSHOT")
- .withConfigurationResource("minikube-with-defaults.properties");
+ .withConfigurationResource("minikube-with-defaults.properties")
+ .setForcedDependencies(
+ Collections.singletonList(new AppArtifact("io.quarkus", "quarkus-minikube", Version.getVersion())));
@ProdBuildResults
private ProdModeTestResults prodModeTestResults;
diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithMixedStyleEnvTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithMixedStyleEnvTest.java
index 3af990afdb88f..33f4d9f110455 100644
--- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithMixedStyleEnvTest.java
+++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/MinikubeWithMixedStyleEnvTest.java
@@ -4,6 +4,7 @@
import java.io.IOException;
import java.nio.file.Path;
+import java.util.Collections;
import java.util.List;
import org.jboss.shrinkwrap.api.ShrinkWrap;
@@ -14,6 +15,8 @@
import io.fabric8.kubernetes.api.model.EnvFromSource;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.quarkus.bootstrap.model.AppArtifact;
+import io.quarkus.builder.Version;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;
@@ -25,7 +28,9 @@ public class MinikubeWithMixedStyleEnvTest {
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(GreetingResource.class))
.setApplicationName("minikube-with-mixed-style-env")
.setApplicationVersion("0.1-SNAPSHOT")
- .withConfigurationResource("minikube-with-mixed-style-env.properties");
+ .withConfigurationResource("minikube-with-mixed-style-env.properties")
+ .setForcedDependencies(
+ Collections.singletonList(new AppArtifact("io.quarkus", "quarkus-minikube", Version.getVersion())));
@ProdBuildResults
private ProdModeTestResults prodModeTestResults;