From 7357d78bc1c31a3b225364dc3d1314c0825b1f0f Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 24 Jul 2023 09:37:56 +0200 Subject: [PATCH] Fix Openshift deployments when using a custom output directory There were two issues: - The resources were not found when using the container image openshift and container image s2i. - The resources were not found at installing them in the cluster. Fix https://github.com/quarkusio/quarkus/issues/34673 --- .../deployment/OpenshiftProcessor.java | 4 +- .../image/s2i/deployment/S2iProcessor.java | 4 +- .../deployment/KubernetesConfig.java | 16 +++ .../deployment/KubernetesDeployer.java | 7 +- .../deployment/KubernetesProcessor.java | 3 +- .../invoker.properties | 4 + .../pom.xml | 115 ++++++++++++++++++ .../src/main/java/org/acme/Hello.java | 16 +++ .../src/main/resources/application.properties | 4 + .../verify.groovy | 19 +++ 10 files changed, 183 insertions(+), 9 deletions(-) create mode 100644 integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/invoker.properties create mode 100644 integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/pom.xml create mode 100644 integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/java/org/acme/Hello.java create mode 100644 integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/resources/application.properties create mode 100644 integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/verify.groovy diff --git a/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java b/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java index 35d2ce3c248e6..1bca77ab95984 100644 --- a/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java +++ b/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java @@ -260,7 +260,7 @@ public void openshiftBuildFromJar(OpenshiftConfig openshiftConfig, Optional openshiftYml = generatedResources .stream() - .filter(r -> r.getName().endsWith("kubernetes" + File.separator + "openshift.yml")) + .filter(r -> r.getName().endsWith(File.separator + "openshift.yml")) .findFirst(); if (openshiftYml.isEmpty()) { @@ -336,7 +336,7 @@ public void openshiftBuildFromNative(OpenshiftConfig openshiftConfig, S2iConfig + kubernetesClient.getMasterUrl() + " in namespace:" + namespace + "."); Optional openshiftYml = generatedResources .stream() - .filter(r -> r.getName().endsWith("kubernetes" + File.separator + "openshift.yml")) + .filter(r -> r.getName().endsWith(File.separator + "openshift.yml")) .findFirst(); if (openshiftYml.isEmpty()) { diff --git a/extensions/container-image/container-image-s2i/deployment/src/main/java/io/quarkus/container/image/s2i/deployment/S2iProcessor.java b/extensions/container-image/container-image-s2i/deployment/src/main/java/io/quarkus/container/image/s2i/deployment/S2iProcessor.java index 81b0da6832b37..8dcb512328c26 100644 --- a/extensions/container-image/container-image-s2i/deployment/src/main/java/io/quarkus/container/image/s2i/deployment/S2iProcessor.java +++ b/extensions/container-image/container-image-s2i/deployment/src/main/java/io/quarkus/container/image/s2i/deployment/S2iProcessor.java @@ -193,7 +193,7 @@ public void s2iBuildFromJar(S2iConfig s2iConfig, ContainerImageConfig containerI Optional openshiftYml = generatedResources .stream() - .filter(r -> r.getName().endsWith("kubernetes" + File.separator + "openshift.yml")) + .filter(r -> r.getName().endsWith(File.separator + "openshift.yml")) .findFirst(); if (openshiftYml.isEmpty()) { @@ -241,7 +241,7 @@ public void s2iBuildFromNative(S2iConfig s2iConfig, ContainerImageConfig contain Optional openshiftYml = generatedResources .stream() - .filter(r -> r.getName().endsWith("kubernetes" + File.separator + "openshift.yml")) + .filter(r -> r.getName().endsWith(File.separator + "openshift.yml")) .findFirst(); if (openshiftYml.isEmpty()) { 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 3a4a79888d640..5067221b90ca9 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 @@ -3,8 +3,11 @@ import static io.quarkus.kubernetes.deployment.Constants.CRONJOB; import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT; import static io.quarkus.kubernetes.deployment.Constants.JOB; +import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES; import static io.quarkus.kubernetes.deployment.Constants.STATEFULSET; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import java.util.List; import java.util.Map; @@ -614,4 +617,17 @@ public KubernetesConfig.DeploymentResourceKind getDeploymentResourceKind(Capabil return DeploymentResourceKind.Deployment; } + + /** + * Resolve the effective output directory where to generate the Kubernetes manifests. + * If the `quarkus.kubernetes.output-directory` property is not provided, then the default project output directory will be + * used. + * + * @param projectOutputDirectory The project output target. + * @return the effective output directory. + */ + public Path getEffectiveOutputDirectory(Path projectOutputDirectory) { + return outputDirectory.map(d -> Paths.get("").toAbsolutePath().resolve(d)) + .orElse(projectOutputDirectory.resolve(KUBERNETES)); + } } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java index f450cea0321aa..26917e6738d6e 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java @@ -110,6 +110,7 @@ public void deploy(KubernetesClientBuildItem kubernetesClientBuilder, List deploymentClusters, Optional selectedDeploymentTarget, OutputTargetBuildItem outputTarget, + KubernetesConfig kubernetesConfig, OpenshiftConfig openshiftConfig, ContainerImageConfig containerImageConfig, ApplicationInfoBuildItem applicationInfo, @@ -137,7 +138,8 @@ public void deploy(KubernetesClientBuildItem kubernetesClientBuilder, try (final KubernetesClient client = kubernetesClientBuilder.buildClient()) { deploymentResult - .produce(deploy(selectedDeploymentTarget.get().getEntry(), client, outputTarget.getOutputDirectory(), + .produce(deploy(selectedDeploymentTarget.get().getEntry(), client, + kubernetesConfig.getEffectiveOutputDirectory(outputTarget.getOutputDirectory()), openshiftConfig, applicationInfo, optionalResourceDefinitions)); } } @@ -191,8 +193,7 @@ private DeploymentResultBuildItem deploy(DeploymentTargetEntry deploymentTarget, String namespace = Optional.ofNullable(client.getNamespace()).orElse("default"); log.info("Deploying to " + deploymentTarget.getName().toLowerCase() + " server: " + client.getMasterUrl() + " in namespace: " + namespace + "."); - File manifest = outputDir.resolve(KUBERNETES).resolve(deploymentTarget.getName().toLowerCase() + ".yml") - .toFile(); + File manifest = outputDir.resolve(deploymentTarget.getName().toLowerCase() + ".yml").toFile(); try (FileInputStream fis = new FileInputStream(manifest)) { KubernetesList list = Serialization.unmarshalAsList(fis); 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 657bac8b41bb5..8ae07053633d2 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 @@ -183,8 +183,7 @@ public void build(ApplicationInfoBuildItem applicationInfo, } }); - Path targetDirectory = kubernetesConfig.outputDirectory.map(d -> Paths.get("").toAbsolutePath().resolve(d)) - .orElse(outputTarget.getOutputDirectory().resolve(KUBERNETES)); + Path targetDirectory = kubernetesConfig.getEffectiveOutputDirectory(outputTarget.getOutputDirectory()); // write the generated resources to the filesystem generatedResourcesMap = session.close(); diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/invoker.properties b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/invoker.properties new file mode 100644 index 0000000000000..978b304282fb2 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/invoker.properties @@ -0,0 +1,4 @@ +# ensure that an attempt to deploy is made, but that the attempt fails (as we don't want to deploy this test application to a cluster that the runner of test may have configured) +invoker.goals=clean package -Dquarkus.kubernetes.output-directory=woo -Dquarkus.kubernetes.deploy=true ${kubernetes-client-api-server-url} +# expect a failure since there is no Kubernetes cluster to deploy to +invoker.buildResult = ${build-result} diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/pom.xml b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/pom.xml new file mode 100644 index 0000000000000..369de652a1e99 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/pom.xml @@ -0,0 +1,115 @@ + + + 4.0.0 + org.acme + openshift-with-output-directory-build-and-deploy + 0.1-SNAPSHOT + + UTF-8 + 3.0.0 + 11 + UTF-8 + 11 + + + + + io.quarkus + quarkus-bom + @project.version@ + pom + import + + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-openshift + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + io.quarkus + quarkus-maven-plugin + @project.version@ + + + + build + + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + native + + + native + + + + native + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${native.surefire.skip} + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + + diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/java/org/acme/Hello.java b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/java/org/acme/Hello.java new file mode 100644 index 0000000000000..95b11f63bda44 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/java/org/acme/Hello.java @@ -0,0 +1,16 @@ +package org.acme; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +@Path("/hello") +public class Hello { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/resources/application.properties b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/resources/application.properties new file mode 100644 index 0000000000000..cdd463e8dca45 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/src/main/resources/application.properties @@ -0,0 +1,4 @@ +# Configuration file +# key = value +quarkus.kubernetes.deployment-target=openshift +quarkus.kubernetes-client.trust-certs=true diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/verify.groovy b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/verify.groovy new file mode 100644 index 0000000000000..b251040850949 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/openshift-with-output-directory-build-and-deploy/verify.groovy @@ -0,0 +1,19 @@ +import io.dekorate.utils.Serialization +import io.fabric8.kubernetes.api.model.KubernetesList +import io.fabric8.openshift.api.model.* + +//Check that file exits +String base = basedir +File openshiftYml = new File(base, "woo/openshift.yml") +assert openshiftYml.exists() +openshiftYml.withInputStream { stream -> + //Check that its parse-able + KubernetesList list = Serialization.unmarshalAsList(stream) + assert list != null + + BuildConfig buildConfig = list.items.find{r -> r.kind == "BuildConfig"} + + //Check that ti contains a Deployment named after the project + assert buildConfig != null + assert buildConfig.metadata.name == "openshift-with-output-directory-build-and-deploy" +}