From d9f1265c10c324df1321cd5be23cc93ef7cc2e12 Mon Sep 17 00:00:00 2001 From: Vincent Sourin Date: Sun, 27 Oct 2024 13:31:27 +0100 Subject: [PATCH] Add nodeSelect capability to kubernetes extension. Fix https://github.com/quarkusio/quarkus/issues/44122 Signed-off-by: Vinche --- .../asciidoc/deploying-to-kubernetes.adoc | 21 +++++ .../deployment/KnativeProcessor.java | 3 + .../deployment/KubernetesCommonHelper.java | 5 ++ .../deployment/NodeSelectorConfig.java | 15 ++++ .../deployment/NodeSelectorConverter.java | 22 +++++ .../deployment/PlatformConfiguration.java | 5 ++ .../AddNodeSelectorDecorator.java | 45 ++++++++++ .../AddNodeSelectorToRevisionDecorator.java | 58 ++++++++++++ .../nodeselector/EditableNodeSelector.java | 23 +++++ .../deployment/nodeselector/NodeSelector.java | 57 ++++++++++++ .../nodeselector/NodeSelectorBuilder.java | 37 ++++++++ .../nodeselector/NodeSelectorFluent.java | 89 +++++++++++++++++++ .../deployment/KubernetesConfigTest.java | 4 + .../application-kubernetes.properties | 3 + .../KubernetesWithNodeSelectorTest.java | 55 ++++++++++++ .../kubernetes-with-nodeselector.properties | 2 + 16 files changed, 444 insertions(+) create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConfig.java create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConverter.java create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorDecorator.java create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorToRevisionDecorator.java create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/EditableNodeSelector.java create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelector.java create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorBuilder.java create mode 100644 extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorFluent.java create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithNodeSelectorTest.java create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-nodeselector.properties diff --git a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc index 40f358744db22..8ab61ce549e68 100644 --- a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc +++ b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc @@ -716,6 +716,27 @@ spec: ip: 10.0.0.0 ---- +=== Add nodeSelector +To add a nodeSelector in the generated `Deployment` (more information can be found in https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes[Kubernetes documentation]), just apply the following configuration: + +[source,properties] +---- +quarkus.kubernetes.node-selector.key=diskType +quarkus.kubernetes.node-selector.value=ssd +---- + +This would generate the following `nodeSelector` section in the `deployment` definition: + +[source,yaml] +---- +kind: Deployment +spec: + template: + spec: + nodeSelector: + diskType: ssd +---- + === Container Resources Management CPU & Memory limits and requests can be applied to a `Container` (more info in https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/[Kubernetes documentation]) using the following configuration: 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 index 03aa9446595b1..fc0b23d8891fb 100644 --- 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 @@ -57,6 +57,7 @@ import io.quarkus.deployment.pkg.PackageConfig; import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem; import io.quarkus.kubernetes.client.spi.KubernetesClientCapabilityBuildItem; +import io.quarkus.kubernetes.deployment.nodeselector.AddNodeSelectorToRevisionDecorator; import io.quarkus.kubernetes.spi.ConfiguratorBuildItem; import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; @@ -290,6 +291,8 @@ public List createDecorators(ApplicationInfoBuildItem applic result.addAll(createAppConfigVolumeAndEnvDecorators(name, config)); config.hostAliases().entrySet().forEach(e -> result.add(new DecoratorBuildItem(KNATIVE, new AddHostAliasesToRevisionDecorator(name, HostAliasConverter.convert(e))))); + config.nodeSelector().ifPresent(n -> result.add(new DecoratorBuildItem(KNATIVE, + new AddNodeSelectorToRevisionDecorator(name, NodeSelectorConverter.convert(n))))); config.sidecars().entrySet().forEach(e -> result .add(new DecoratorBuildItem(KNATIVE, new AddSidecarToRevisionDecorator(name, ContainerConverter.convert(e))))); 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 index 68160092bc238..90420afca80f6 100644 --- 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 @@ -82,6 +82,7 @@ import io.quarkus.deployment.pkg.PackageConfig; import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem; import io.quarkus.kubernetes.client.spi.KubernetesClientCapabilityBuildItem; +import io.quarkus.kubernetes.deployment.nodeselector.AddNodeSelectorDecorator; import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; @@ -852,6 +853,10 @@ private static List createPodDecorators(String target, Strin config.hostAliases().entrySet().forEach(e -> result .add(new DecoratorBuildItem(target, new AddHostAliasesDecorator(name, HostAliasConverter.convert(e))))); + config.nodeSelector() + .ifPresent(n -> result.add( + new DecoratorBuildItem(target, new AddNodeSelectorDecorator(name, NodeSelectorConverter.convert(n))))); + config.initContainers().entrySet().forEach(e -> result .add(new DecoratorBuildItem(target, new AddInitContainerDecorator(name, ContainerConverter.convert(e))))); diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConfig.java new file mode 100644 index 0000000000000..3085f11d96b0e --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConfig.java @@ -0,0 +1,15 @@ +package io.quarkus.kubernetes.deployment; + +import java.util.Optional; + +public interface NodeSelectorConfig { + /** + * The key of the nodeSelector. + */ + Optional key(); + + /** + * The value of the nodeSelector. + */ + Optional value(); +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConverter.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConverter.java new file mode 100644 index 0000000000000..99a71fd72c896 --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/NodeSelectorConverter.java @@ -0,0 +1,22 @@ +package io.quarkus.kubernetes.deployment; + +import io.quarkus.kubernetes.deployment.nodeselector.NodeSelector; +import io.quarkus.kubernetes.deployment.nodeselector.NodeSelectorBuilder; + +public class NodeSelectorConverter { + + public static NodeSelector convert(NodeSelectorConfig nodeSelector) { + return convertToBuilder(nodeSelector).build(); + } + + public static NodeSelectorBuilder convertToBuilder(NodeSelectorConfig nodeSelector) { + NodeSelectorBuilder b = new NodeSelectorBuilder(); + if (nodeSelector.key().isPresent() && nodeSelector.value().isPresent()) { + b.withKey(nodeSelector.key().get()); + b.withValue(nodeSelector.value().get()); + } + + return b; + } + +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java index 11c78c45cc24f..51a8e40ab7fc3 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java @@ -204,6 +204,11 @@ public interface PlatformConfiguration extends EnvVarHolder { @WithName("hostaliases") Map hostAliases(); + /** + * The nodeSelector. + */ + Optional nodeSelector(); + /** * Resources requirements. */ diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorDecorator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorDecorator.java new file mode 100644 index 0000000000000..d9ba4f42dacbd --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorDecorator.java @@ -0,0 +1,45 @@ +package io.quarkus.kubernetes.deployment.nodeselector; + +import java.util.Objects; + +import io.dekorate.kubernetes.decorator.NamedResourceDecorator; +import io.dekorate.utils.Strings; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.PodSpecFluent; + +/** + * Copied from dekorate. + * TODO: This decorator should be removed and replaced by the Dekorate AddNodeSelectorDecorator class after + * https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped. + */ +public class AddNodeSelectorDecorator extends NamedResourceDecorator> { + + private final NodeSelector nodeSelector; + + public AddNodeSelectorDecorator(String deploymentName, NodeSelector nodeSelector) { + super(deploymentName); + this.nodeSelector = nodeSelector; + } + + public void andThenVisit(PodSpecFluent podSpec, ObjectMeta resourceMeta) { + if (Strings.isNotNullOrEmpty(nodeSelector.getKey()) && Strings.isNotNullOrEmpty(nodeSelector.getValue())) { + podSpec.removeFromNodeSelector(nodeSelector.getKey()); + podSpec.addToNodeSelector(nodeSelector.getKey(), nodeSelector.getValue()); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + AddNodeSelectorDecorator that = (AddNodeSelectorDecorator) o; + return Objects.equals(nodeSelector, that.nodeSelector); + } + + @Override + public int hashCode() { + return Objects.hash(nodeSelector); + } +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorToRevisionDecorator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorToRevisionDecorator.java new file mode 100644 index 0000000000000..1e0c03354c8d6 --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/AddNodeSelectorToRevisionDecorator.java @@ -0,0 +1,58 @@ +package io.quarkus.kubernetes.deployment.nodeselector; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import io.dekorate.kubernetes.decorator.NamedResourceDecorator; +import io.dekorate.utils.Strings; +import io.fabric8.knative.serving.v1.RevisionSpecFluent; +import io.fabric8.kubernetes.api.model.ObjectMeta; + +/** + * Copied from dekorate. + * TODO: This decorator should be removed and replaced by the Dekorate AddNodeSelectorToRevisionDecorator class after + * https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped. + */ +public class AddNodeSelectorToRevisionDecorator extends NamedResourceDecorator> { + + private final NodeSelector nodeSelector; + + public AddNodeSelectorToRevisionDecorator(NodeSelector nodeSelector) { + this(ANY, nodeSelector); + } + + public AddNodeSelectorToRevisionDecorator(String deploymentName, NodeSelector nodeSelector) { + super(deploymentName); + this.nodeSelector = nodeSelector; + } + + public void andThenVisit(RevisionSpecFluent revisionSpec, ObjectMeta resourceMeta) { + if (Strings.isNotNullOrEmpty(nodeSelector.getKey()) && Strings.isNotNullOrEmpty(nodeSelector.getValue())) { + Map existing = revisionSpec.getNodeSelector(); + + if (existing == null) + existing = new HashMap<>(); + else + existing.clear(); + + existing.put(nodeSelector.getKey(), nodeSelector.getValue()); + revisionSpec.withNodeSelector(existing); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + AddNodeSelectorToRevisionDecorator that = (AddNodeSelectorToRevisionDecorator) o; + return Objects.equals(nodeSelector, that.nodeSelector); + } + + @Override + public int hashCode() { + return Objects.hash(nodeSelector); + } +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/EditableNodeSelector.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/EditableNodeSelector.java new file mode 100644 index 0000000000000..7edfee0e76cec --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/EditableNodeSelector.java @@ -0,0 +1,23 @@ +package io.quarkus.kubernetes.deployment.nodeselector; + +import io.fabric8.kubernetes.api.builder.Editable; + +/** + * Copied from dekorate. + * TODO: This should be removed and replaced after + * https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped. + */ +public class EditableNodeSelector extends NodeSelector implements Editable { + public EditableNodeSelector() { + super(); + } + + public EditableNodeSelector(String key, String value) { + super(key, value); + } + + public NodeSelectorBuilder edit() { + return new NodeSelectorBuilder(this); + } + +} \ No newline at end of file diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelector.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelector.java new file mode 100644 index 0000000000000..0a7ed8ba6ffa6 --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelector.java @@ -0,0 +1,57 @@ +package io.quarkus.kubernetes.deployment.nodeselector; + +import io.fabric8.kubernetes.api.model.NodeSelectorBuilder; + +/** + * Copied from dekorate. + * TODO: This should be removed and replaced after + * https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped. + */ +public class NodeSelector { + private String key; + private String value; + + public NodeSelector() { + } + + public NodeSelector(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return this.key; + } + + public String getValue() { + return this.value; + } + + public static NodeSelectorBuilder newBuilder() { + return new NodeSelectorBuilder(); + } + + public static NodeSelectorBuilder newBuilderFromDefaults() { + return new NodeSelectorBuilder(); + } + + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + NodeSelector that = (NodeSelector) o; + if (!java.util.Objects.equals(key, that.key)) + return false; + if (!java.util.Objects.equals(value, that.value)) + return false; + return true; + } + + public int hashCode() { + return java.util.Objects.hash(key, value, super.hashCode()); + } + +} \ No newline at end of file diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorBuilder.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorBuilder.java new file mode 100644 index 0000000000000..50ebd1054b9b4 --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorBuilder.java @@ -0,0 +1,37 @@ +package io.quarkus.kubernetes.deployment.nodeselector; + +import io.fabric8.kubernetes.api.builder.VisitableBuilder; + +/** + * Copied from dekorate. + * TODO: This should be removed and replaced after + * https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped. + */ +public class NodeSelectorBuilder extends NodeSelectorFluent + implements VisitableBuilder { + + public NodeSelectorBuilder() { + this(new NodeSelector()); + } + + public NodeSelectorBuilder(NodeSelectorFluent fluent) { + this(fluent, new NodeSelector()); + } + + public NodeSelectorBuilder(NodeSelectorFluent fluent, NodeSelector instance) { + this.fluent = fluent; + fluent.copyInstance(instance); + } + + public NodeSelectorBuilder(NodeSelector instance) { + this.fluent = this; + this.copyInstance(instance); + } + + NodeSelectorFluent fluent; + + public EditableNodeSelector build() { + EditableNodeSelector buildable = new EditableNodeSelector(fluent.getKey(), fluent.getValue()); + return buildable; + } +} \ No newline at end of file diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorFluent.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorFluent.java new file mode 100644 index 0000000000000..106ed6672e9f2 --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/nodeselector/NodeSelectorFluent.java @@ -0,0 +1,89 @@ +package io.quarkus.kubernetes.deployment.nodeselector; + +import io.fabric8.kubernetes.api.builder.BaseFluent; + +/** + * Copied from dekorate. + * TODO: This should be removed and replaced after + * https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped. + */ +public class NodeSelectorFluent> extends BaseFluent { + private String key; + private String value; + + public NodeSelectorFluent() { + } + + public NodeSelectorFluent(NodeSelector instance) { + this.copyInstance(instance); + } + + protected void copyInstance(NodeSelector instance) { + instance = (instance != null ? instance : new NodeSelector()); + if (instance != null) { + this.withKey(instance.getKey()); + this.withValue(instance.getValue()); + } + } + + public String getKey() { + return this.key; + } + + public A withKey(String key) { + this.key = key; + return (A) this; + } + + public boolean hasKey() { + return this.key != null; + } + + public String getValue() { + return this.value; + } + + public A withValue(String value) { + this.value = value; + return (A) this; + } + + public boolean hasValue() { + return this.value != null; + } + + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + NodeSelectorFluent that = (NodeSelectorFluent) o; + if (!java.util.Objects.equals(key, that.key)) + return false; + if (!java.util.Objects.equals(value, that.value)) + return false; + return true; + } + + public int hashCode() { + return java.util.Objects.hash(key, value, super.hashCode()); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + if (key != null) { + sb.append("key:"); + sb.append(key + ","); + } + if (value != null) { + sb.append("value:"); + sb.append(value); + } + sb.append("}"); + return sb.toString(); + } + +} \ No newline at end of file diff --git a/extensions/kubernetes/vanilla/deployment/src/test/java/io/quarkus/kubernetes/deployment/KubernetesConfigTest.java b/extensions/kubernetes/vanilla/deployment/src/test/java/io/quarkus/kubernetes/deployment/KubernetesConfigTest.java index 4e75fe48d3e1f..1ddc093509987 100644 --- a/extensions/kubernetes/vanilla/deployment/src/test/java/io/quarkus/kubernetes/deployment/KubernetesConfigTest.java +++ b/extensions/kubernetes/vanilla/deployment/src/test/java/io/quarkus/kubernetes/deployment/KubernetesConfigTest.java @@ -228,6 +228,10 @@ void kubernetes() throws Exception { assertEquals("konoha", hostAliases.get("ip")); assertIterableEquals(List.of("dev", "qly", "prod"), (Iterable) hostAliases.get("hostnames")); + Map nodeSelector = deployment().map("spec").map("template").map("spec").asMap("nodeSelector"); + assertTrue(nodeSelector.containsKey("jutsu")); + assertEquals("katon", nodeSelector.get("jutsu")); + Map limits = container().map("resources").asMap("limits"); assertEquals("fuuton", limits.get("cpu")); assertEquals("raiton", limits.get("memory")); diff --git a/extensions/kubernetes/vanilla/deployment/src/test/resources/application-kubernetes.properties b/extensions/kubernetes/vanilla/deployment/src/test/resources/application-kubernetes.properties index 467f9ad9fcb82..bdf4d8a914544 100644 --- a/extensions/kubernetes/vanilla/deployment/src/test/resources/application-kubernetes.properties +++ b/extensions/kubernetes/vanilla/deployment/src/test/resources/application-kubernetes.properties @@ -132,6 +132,9 @@ quarkus.kubernetes.deployment-target=kubernetes,openshift,knative,minikube quarkus.kubernetes.hostaliases.konoha.ip=0.0.0.0 quarkus.kubernetes.hostaliases.konoha.hostnames=dev,qly,prod +quarkus.kubernetes.node-selector.key=jutsu +quarkus.kubernetes.node-selector.value=katon + quarkus.kubernetes.resources.limits.cpu=fuuton quarkus.kubernetes.resources.limits.memory=raiton quarkus.kubernetes.resources.requests.cpu=katon diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithNodeSelectorTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithNodeSelectorTest.java new file mode 100644 index 0000000000000..950eb433c088d --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithNodeSelectorTest.java @@ -0,0 +1,55 @@ +package io.quarkus.it.kubernetes; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.quarkus.test.ProdBuildResults; +import io.quarkus.test.ProdModeTestResults; +import io.quarkus.test.QuarkusProdModeTest; + +public class KubernetesWithNodeSelectorTest { + + @RegisterExtension + static final QuarkusProdModeTest config = new QuarkusProdModeTest() + .withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class)) + .setApplicationName("nodeselector") + .setApplicationVersion("0.1-SNAPSHOT") + .withConfigurationResource("kubernetes-with-nodeselector.properties"); + + @ProdBuildResults + private ProdModeTestResults prodModeTestResults; + + @Test + public void assertGeneratedResources() throws IOException { + Map expectedNodeSelector = Map.of("diskType", "ssd"); + + Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes"); + assertThat(kubernetesDir) + .isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.json")) + .isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.yml")); + List kubernetesList = DeserializationUtil + .deserializeAsList(kubernetesDir.resolve("kubernetes.yml")); + assertThat(kubernetesList.get(0)).isInstanceOfSatisfying(Deployment.class, d -> { + assertThat(d.getMetadata()).satisfies(m -> { + assertThat(m.getName()).isEqualTo("nodeselector"); + }); + + assertThat(d.getSpec()).satisfies(deploymentSpec -> { + assertThat(deploymentSpec.getTemplate()).satisfies(t -> { + assertThat(t.getSpec()).satisfies(podSpec -> { + assertThat(podSpec.getNodeSelector()).containsExactlyEntriesOf(expectedNodeSelector); + }); + }); + }); + }); + } +} diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-nodeselector.properties b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-nodeselector.properties new file mode 100644 index 0000000000000..b14b91278ff67 --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-nodeselector.properties @@ -0,0 +1,2 @@ +quarkus.kubernetes.node-selector.key=diskType +quarkus.kubernetes.node-selector.value=ssd \ No newline at end of file