diff --git a/quarkus/addons/kubernetes/integration-tests/pom.xml b/quarkus/addons/kubernetes/integration-tests/pom.xml
new file mode 100644
index 00000000000..51163e99297
--- /dev/null
+++ b/quarkus/addons/kubernetes/integration-tests/pom.xml
@@ -0,0 +1,133 @@
+
+
+ 4.0.0
+
+ org.kie.kogito
+ kogito-addons-quarkus-kubernetes-parent
+ 2.0.0-SNAPSHOT
+
+
+ kogito-addons-quarkus-kubernetes-integration-tests
+ Kogito Add-On Kubernetes - Integration Tests
+
+
+
+
+ org.kie.kogito
+ kogito-quarkus-bom
+ ${project.version}
+ pom
+ import
+
+
+
+
+
+
+ io.quarkus
+ quarkus-cache
+
+
+ io.quarkus
+ quarkus-smallrye-openapi
+
+
+ org.kie.kogito
+ kogito-quarkus-serverless-workflow
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+ io.quarkus
+ quarkus-resteasy-jackson
+
+
+ org.kie.kogito
+ kogito-addons-quarkus-kubernetes
+
+
+ org.kie.kogito
+ kogito-addons-quarkus-fabric8-kubernetes-service-catalog
+
+
+ io.quarkus
+ quarkus-kubernetes
+
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.quarkus
+ quarkus-test-kubernetes-client
+ test
+
+
+ io.rest-assured
+ rest-assured
+
+
+ org.kie.kogito
+ kogito-addons-quarkus-fabric8-kubernetes-service-catalog-test-utils
+ test
+
+
+
+ org.kie.kogito
+ kogito-quarkus-workflow-common-deployment
+ test
+
+
+ org.kie.kogito
+ kogito-addons-quarkus-messaging-deployment
+ test
+
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+ true
+ ${skipTests}
+
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+
+
+
+ native
+
+
+ native
+
+
+
+ native
+
+
+
+
\ No newline at end of file
diff --git a/quarkus/addons/kubernetes/integration-tests/src/main/java/org/kie/kogito/addons/quarkus/kubernetes/Foo.java b/quarkus/addons/kubernetes/integration-tests/src/main/java/org/kie/kogito/addons/quarkus/kubernetes/Foo.java
new file mode 100644
index 00000000000..abcbda47995
--- /dev/null
+++ b/quarkus/addons/kubernetes/integration-tests/src/main/java/org/kie/kogito/addons/quarkus/kubernetes/Foo.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.kie.kogito.addons.quarkus.kubernetes;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+@Path("/foo")
+@Produces(MediaType.TEXT_PLAIN)
+public class Foo {
+
+ @Inject
+ @ConfigProperty(name = "my_service")
+ String service;
+
+ @GET
+ public String getWorkflowType() {
+ return service;
+ }
+}
diff --git a/quarkus/addons/kubernetes/integration-tests/src/main/resources/application.properties b/quarkus/addons/kubernetes/integration-tests/src/main/resources/application.properties
new file mode 100644
index 00000000000..0979c469c2a
--- /dev/null
+++ b/quarkus/addons/kubernetes/integration-tests/src/main/resources/application.properties
@@ -0,0 +1 @@
+my_service=${knative:services.v1.serving.knative.dev/default/serverless-workflow-greeting-quarkus}/path
\ No newline at end of file
diff --git a/quarkus/addons/kubernetes/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/kubernetes/ConfigValueExpanderIT.java b/quarkus/addons/kubernetes/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/kubernetes/ConfigValueExpanderIT.java
new file mode 100644
index 00000000000..c22bb072b11
--- /dev/null
+++ b/quarkus/addons/kubernetes/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/kubernetes/ConfigValueExpanderIT.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.kie.kogito.addons.quarkus.kubernetes;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+import io.quarkus.test.kubernetes.client.KubernetesTestServer;
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+import static org.kie.kogito.addons.quarkus.k8s.test.utils.KnativeResourceDiscoveryTestUtil.createServiceIfNotExists;
+
+@QuarkusIntegrationTest
+@WithKubernetesTestServer
+class ConfigValueExpanderIT {
+
+ private static final String NAMESPACE = "default";
+
+ private static final String SERVICENAME = "serverless-workflow-greeting-quarkus";
+
+ @KubernetesTestServer
+ KubernetesServer mockServer;
+
+ @BeforeEach
+ void beforeEach() {
+ createServiceIfNotExists(mockServer, "knative/quarkus-greeting.yaml", NAMESPACE, SERVICENAME);
+ }
+
+ @Test
+ void test() {
+ given().when()
+ .get("/foo")
+ .then()
+ .statusCode(200)
+ .body(is("http://serverless-workflow-greeting-quarkus.test.10.99.154.147.sslip.io/path"));
+ }
+}
diff --git a/quarkus/addons/kubernetes/integration-tests/src/test/resources/knative/quarkus-greeting.yaml b/quarkus/addons/kubernetes/integration-tests/src/test/resources/knative/quarkus-greeting.yaml
new file mode 100644
index 00000000000..712d182b28e
--- /dev/null
+++ b/quarkus/addons/kubernetes/integration-tests/src/test/resources/knative/quarkus-greeting.yaml
@@ -0,0 +1,54 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ annotations:
+ serving.knative.dev/creator: minikube-user
+ serving.knative.dev/lastModifier: minikube-user
+ creationTimestamp: '2022-08-17T13:58:53Z'
+ generation: 1
+ name: serverless-workflow-greeting-quarkus
+ resourceVersion: '43817'
+ uid: 98530cb6-3274-4d0c-b654-a82645cda058
+spec:
+ template:
+ metadata:
+ annotations:
+ client.knative.dev/updateTimestamp: '2022-08-17T13:58:53Z'
+ client.knative.dev/user-image: kiegroup/serverless-workflow-greeting-quarkus:1.0
+ creationTimestamp:
+ spec:
+ containerConcurrency: 0
+ containers:
+ - image: kiegroup/serverless-workflow-greeting-quarkus:1.0
+ name: user-container
+ readinessProbe:
+ successThreshold: 1
+ tcpSocket:
+ port: 0
+ resources: { }
+ enableServiceLinks: false
+ timeoutSeconds: 300
+ traffic:
+ - latestRevision: true
+ percent: 100
+status:
+ address:
+ url: http://serverless-workflow-greeting-quarkus.test.svc.cluster.local
+ conditions:
+ - lastTransitionTime: '2022-08-17T13:59:00Z'
+ status: 'True'
+ type: ConfigurationsReady
+ - lastTransitionTime: '2022-08-17T13:59:00Z'
+ status: 'True'
+ type: Ready
+ - lastTransitionTime: '2022-08-17T13:59:00Z'
+ status: 'True'
+ type: RoutesReady
+ latestCreatedRevisionName: serverless-workflow-greeting-quarkus-00001
+ latestReadyRevisionName: serverless-workflow-greeting-quarkus-00001
+ observedGeneration: 1
+ traffic:
+ - latestRevision: true
+ percent: 100
+ revisionName: serverless-workflow-greeting-quarkus-00001
+ url: http://serverless-workflow-greeting-quarkus.test.10.99.154.147.sslip.io
diff --git a/quarkus/addons/kubernetes/pom.xml b/quarkus/addons/kubernetes/pom.xml
index 688556e4fd0..501c44cf22c 100644
--- a/quarkus/addons/kubernetes/pom.xml
+++ b/quarkus/addons/kubernetes/pom.xml
@@ -16,6 +16,7 @@
runtime
deployment
+ integration-tests
diff --git a/quarkus/addons/kubernetes/runtime/src/main/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpander.java b/quarkus/addons/kubernetes/runtime/src/main/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpander.java
index 43fa7d04ce1..a45a13b7b61 100644
--- a/quarkus/addons/kubernetes/runtime/src/main/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpander.java
+++ b/quarkus/addons/kubernetes/runtime/src/main/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpander.java
@@ -15,6 +15,8 @@
*/
package org.kie.kogito.addons.quarkus.k8s.config;
+import java.util.Arrays;
+
import org.kie.kogito.addons.k8s.resource.catalog.KubernetesProtocol;
import io.smallrye.config.ConfigValue;
@@ -28,22 +30,42 @@ class ConfigValueExpander {
}
ConfigValue expand(ConfigValue configValue) {
- if (configValue == null || !valueContainsDiscovery(configValue)) {
- return configValue;
+ if (configValue != null && configValue.getRawValue() != null) {
+ String serviceCoordinates = extractServiceCoordinates(configValue.getRawValue());
+ if (serviceCoordinates != null) {
+ return kubeDiscoveryConfigCache.get(configValue.getName(), serviceCoordinates)
+ .map(value -> interpolate(configValue.getRawValue(), value))
+ .map(configValue::withValue)
+ .orElse(configValue);
+ }
}
- return kubeDiscoveryConfigCache.get(configValue.getName(), configValue.getValue())
- .map(configValue::withValue)
- .orElse(configValue);
+ return configValue;
+ }
+
+ public static String interpolate(String input, String replacement) {
+ int startIndex = input.indexOf("${");
+ int endIndex = input.indexOf("}", startIndex);
+
+ return input.substring(0, startIndex) + replacement + input.substring(endIndex + 1);
}
- private boolean valueContainsDiscovery(ConfigValue configValue) {
- for (KubernetesProtocol protocol : KubernetesProtocol.values()) {
- String value = configValue.getValue();
- if (value != null && value.startsWith(protocol.getValue() + ":")) {
- return true;
+ static String extractServiceCoordinates(String rawValue) {
+ int startIndex = rawValue.indexOf("${");
+ int endIndex = rawValue.indexOf("}", startIndex);
+
+ if (startIndex != -1 && endIndex != -1) {
+ String substring = rawValue.substring(startIndex + 2, endIndex);
+
+ boolean isKubernetesServiceCoordinate = Arrays.stream(KubernetesProtocol.values())
+ .map(KubernetesProtocol::getValue)
+ .anyMatch(protocol -> substring.startsWith(protocol + ":"));
+
+ if (isKubernetesServiceCoordinate) {
+ return substring;
}
}
- return false;
+
+ return null;
}
}
diff --git a/quarkus/addons/kubernetes/runtime/src/test/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpanderTest.java b/quarkus/addons/kubernetes/runtime/src/test/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpanderTest.java
index 73cc4e0709d..f9d3e0330d1 100644
--- a/quarkus/addons/kubernetes/runtime/src/test/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpanderTest.java
+++ b/quarkus/addons/kubernetes/runtime/src/test/java/org/kie/kogito/addons/quarkus/k8s/config/ConfigValueExpanderTest.java
@@ -16,9 +16,12 @@
package org.kie.kogito.addons.quarkus.k8s.config;
import java.util.Optional;
+import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import io.smallrye.config.ConfigValue;
@@ -27,32 +30,46 @@
class ConfigValueExpanderTest {
+ static Stream extractServiceCoordinatesSource() {
+ return Stream.of(
+ Arguments.of("${kubernetes:pods.v1/kie/kogito}/path", "kubernetes:pods.v1/kie/kogito"),
+ Arguments.of("${knative:services.v1.serving.knative.dev/default/serverless-workflow-greeting-quarkus}/path",
+ "knative:services.v1.serving.knative.dev/default/serverless-workflow-greeting-quarkus"));
+ }
+
+ @ParameterizedTest
+ @MethodSource("extractServiceCoordinatesSource")
+ void extractServiceCoordinates(String expandableValue, String expectedCoordinate) {
+ assertThat(ConfigValueExpander.extractServiceCoordinates(expandableValue))
+ .isEqualTo(expectedCoordinate);
+ }
+
@ParameterizedTest
- @ValueSource(strings = { "kubernetes:pods.v1/kie/kogito", "openshift:pods.v1/kie/kogito", "knative:kie/kogito" })
+ @ValueSource(strings = { "${kubernetes:pods.v1/kie/kogito}/path", "${openshift:pods.v1/kie/kogito}/path", "${knative:kie/kogito}/path" })
void expandable(String expandableValues) {
- String expectedValue = "https://localhost/8080";
+ String expectedUrl = "https://localhost/8080";
+ String expectedValue = expectedUrl + "/path";
- ConfigValueExpander expander = new ConfigValueExpander(new FakeKubeDiscoveryConfigCache(expectedValue));
+ ConfigValueExpander expander = new ConfigValueExpander(new FakeKubeDiscoveryConfigCache(expectedUrl));
ConfigValue configValue = ConfigValue.builder()
- .withValue(expandableValues)
+ .withRawValue(expandableValues)
.build();
assertThat(expander.expand(configValue).getValue())
.isEqualTo(expectedValue);
}
- @Test
- void nonExpandable() {
- String nonExpandableValue = "https://localhost/8080";
-
+ @ParameterizedTest
+ @ValueSource(strings = { "https://localhost/8080", "kubernetes:pods.v1/kie/kogito", "openshift:pods.v1/kie/kogito", "knative:kie/kogito", "${something}" })
+ void nonExpandable(String nonExpandableValue) {
ConfigValueExpander expander = new ConfigValueExpander(new FakeKubeDiscoveryConfigCache("should not be returned"));
ConfigValue configValue = ConfigValue.builder()
- .withValue(nonExpandableValue)
+ .withRawValue(nonExpandableValue)
.build();
- assertThat(expander.expand(configValue).getValue())
+ assertThat(expander.expand(configValue).getRawValue())
.isEqualTo(nonExpandableValue);
}
@@ -61,7 +78,7 @@ void nullShouldBeNonExpandable() {
ConfigValueExpander expander = new ConfigValueExpander(new FakeKubeDiscoveryConfigCache("should not be returned"));
ConfigValue configValue = ConfigValue.builder()
- .withValue(null)
+ .withRawValue(null)
.build();
assertThat(expander.expand(configValue).getValue())