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 859dcb2d39e89d..2b7edaaaf34d31 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 @@ -157,12 +157,6 @@ public static List createDecorators(Project project, String : 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; } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java index a1c81fa1d64154..da30d419089cc1 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java @@ -14,6 +14,19 @@ @ConfigRoot public class OpenshiftConfig implements PlatformConfiguration { + public static enum OpenshiftFlavor { + v3, + v4; + } + + /** + * The openshift flavor / version to use. + * Older versions of Openshift have minor diferrences in the labels and fields they support. + * This option allows users to have their manifests automatically aligned to they openshift 'flavor' they use. + */ + @ConfigItem(defaultValue = "v4") + OpenshiftFlavor flavor; + /** * The name of the group this component belongs too */ 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 index 5c6134593ca935..930381a8c99e1d 100644 --- 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 @@ -8,6 +8,7 @@ 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.OpenshiftConfig.OpenshiftFlavor.v3; import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.DEFAULT_PRIORITY; import java.util.ArrayList; @@ -130,6 +131,20 @@ public List createDecorators(ApplicationInfoBuildItem applic annotations, labels, command, ports, livenessPath, readinessPath, roles, roleBindings)); + if (config.flavor == v3) { + //Openshift 3.x doesn't recognize 'app.kubernetes.io/name', it uses 'app' instead. + //The decorator will be applied even on non-openshift resources is it may affect for example: knative + result.add(new DecoratorBuildItem(new AddLabelDecorator(name, "app", name))); + + // 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. + //The decorators will be applied even on non-openshift resources is they may affect for example: knative + result.add(new DecoratorBuildItem(new RemoveOptionalFromSecretEnvSourceDecorator())); + result.add(new DecoratorBuildItem(new RemoveOptionalFromConfigMapEnvSourceDecorator())); + result.add(new DecoratorBuildItem(new RemoveOptionalFromSecretKeySelectorDecorator())); + result.add(new DecoratorBuildItem(new RemoveOptionalFromConfigMapKeySelectorDecorator())); + } + if (config.getReplicas() != 1) { result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyReplicasDecorator(name, config.getReplicas()))); } diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftV3Test.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftV3Test.java new file mode 100644 index 00000000000000..e8c63ad71a7dcf --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftV3Test.java @@ -0,0 +1,78 @@ +package io.quarkus.it.kubernetes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.assertj.core.api.AbstractObjectAssert; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +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.Service; +import io.quarkus.test.ProdBuildResults; +import io.quarkus.test.ProdModeTestResults; +import io.quarkus.test.QuarkusProdModeTest; + +public class OpenshiftV3Test { + + @RegisterExtension + static final QuarkusProdModeTest config = new QuarkusProdModeTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(GreetingResource.class)) + .setApplicationName("openshift-v3") + .setApplicationVersion("0.1-SNAPSHOT") + .withConfigurationResource("openshift-v3.properties"); + + @ProdBuildResults + private ProdModeTestResults prodModeTestResults; + + @Test + public void assertGeneratedResources() throws IOException { + Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes"); + assertThat(kubernetesDir) + .isDirectoryContaining(p -> p.getFileName().endsWith("openshift.json")) + .isDirectoryContaining(p -> p.getFileName().endsWith("openshift.yml")) + .satisfies(p -> assertThat(p.toFile().listFiles()).hasSize(2)); + List openshiftList = DeserializationUtil + .deserializeAsList(kubernetesDir.resolve("openshift.yml")); + + assertThat(openshiftList).filteredOn(h -> "DeploymentConfig".equals(h.getKind())).singleElement().satisfies(h -> { + assertThat(h.getMetadata()).satisfies(m -> { + assertThat(m.getName()).isEqualTo("openshift-v3"); + assertThat(m.getLabels().get("app.openshift.io/runtime")).isEqualTo("quarkus"); + assertThat(m.getLabels().get("app")).isEqualTo("openshift-v3"); + assertThat(m.getNamespace()).isNull(); + }); + AbstractObjectAssert specAssert = assertThat(h).extracting("spec"); + specAssert.extracting("replicas").isEqualTo(1); + specAssert.extracting("triggers").isInstanceOfSatisfying(Collection.class, c -> { + assertThat(c).isEmpty(); + }); + specAssert.extracting("selector").isInstanceOfSatisfying(Map.class, selectorsMap -> { + assertThat(selectorsMap).containsOnly(entry("app.kubernetes.io/name", "openshift-v3"), + entry("app.kubernetes.io/version", "0.1-SNAPSHOT")); + }); + }); + + assertThat(openshiftList).filteredOn(h -> "Service".equals(h.getKind())).singleElement().satisfies(h -> { + assertThat(h).isInstanceOfSatisfying(Service.class, s -> { + assertThat(s.getMetadata()).satisfies(m -> { + assertThat(m.getNamespace()).isNull(); + assertThat(m.getLabels().get("app")).isEqualTo("openshift-v3"); + }); + + assertThat(s.getSpec()).satisfies(spec -> { + assertThat(spec.getSelector()).containsOnly(entry("app.kubernetes.io/name", "openshift-v3"), + entry("app.kubernetes.io/version", "0.1-SNAPSHOT")); + }); + }); + }); + } +} diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/openshift-v3.properties b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/openshift-v3.properties new file mode 100644 index 00000000000000..22bc2bebdb9041 --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/openshift-v3.properties @@ -0,0 +1,2 @@ +quarkus.kubernetes.deployment-target=openshift +quarkus.openshift.flavor=v3 \ No newline at end of file