diff --git a/operator/pom.xml b/operator/pom.xml
index d563589b..1ab6f661 100644
--- a/operator/pom.xml
+++ b/operator/pom.xml
@@ -73,6 +73,10 @@
+
+ io.fabric8
+ openshift-client
+
io.fabric8
kubernetes-httpclient-okhttp
diff --git a/operator/src/main/java/com/datastax/oss/kaap/controllers/AbstractController.java b/operator/src/main/java/com/datastax/oss/kaap/controllers/AbstractController.java
index ea1921aa..9f58ee70 100644
--- a/operator/src/main/java/com/datastax/oss/kaap/controllers/AbstractController.java
+++ b/operator/src/main/java/com/datastax/oss/kaap/controllers/AbstractController.java
@@ -37,6 +37,8 @@
import io.fabric8.kubernetes.api.model.OwnerReferenceBuilder;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.openshift.api.model.Route;
+import io.fabric8.openshift.client.OpenShiftClient;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
@@ -64,6 +66,7 @@ public abstract class AbstractController {
protected final KubernetesClient client;
+ protected final OpenShiftClient openShiftClient;
private final Validator validator;
@Inject
OperatorRuntimeConfiguration operatorRuntimeConfiguration;
@@ -76,9 +79,14 @@ public AbstractController() {
public AbstractController(KubernetesClient client) {
this.client = client;
this.validator = createValidator();
+ openShiftClient = isOpenShiftCluster(client) ? client.adapt(OpenShiftClient.class) : null;
}
+ protected boolean isOpenShiftCluster(KubernetesClient client) {
+ return client != null && client.supports(Route.class);
+ }
+
private Validator createValidator() {
final HibernateValidatorConfiguration configuration = (HibernateValidatorConfiguration)
Validation.byDefaultProvider().configure();
diff --git a/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyController.java b/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyController.java
index 2c48f7f4..7c5942e1 100644
--- a/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyController.java
+++ b/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyController.java
@@ -105,6 +105,7 @@ protected void patchResourceSet(SetInfo set
resourceFactory.patchConfigMap();
resourceFactory.patchConfigMapWsConfig();
resourceFactory.patchService();
+ resourceFactory.patchOpenShiftRoutes(openShiftClient);
resourceFactory.patchDeployment();
}
@@ -122,6 +123,7 @@ protected void deleteResourceSet(SetInfo se
@Override
protected void patchCommonResources(SetInfo set) {
set.getResourceFactory().patchService();
+ set.getResourceFactory().patchOpenShiftRoutes(openShiftClient);
}
@Override
diff --git a/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyResourcesFactory.java b/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyResourcesFactory.java
index d9345a47..c0049557 100644
--- a/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyResourcesFactory.java
+++ b/operator/src/main/java/com/datastax/oss/kaap/controllers/proxy/ProxyResourcesFactory.java
@@ -30,6 +30,7 @@
import io.fabric8.kubernetes.api.model.ContainerPort;
import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
import io.fabric8.kubernetes.api.model.EnvFromSourceBuilder;
+import io.fabric8.kubernetes.api.model.IntOrString;
import io.fabric8.kubernetes.api.model.OwnerReference;
import io.fabric8.kubernetes.api.model.Probe;
import io.fabric8.kubernetes.api.model.Service;
@@ -41,6 +42,10 @@
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.openshift.api.model.Route;
+import io.fabric8.openshift.api.model.RouteBuilder;
+import io.fabric8.openshift.api.model.RouteFluent;
+import io.fabric8.openshift.client.OpenShiftClient;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -628,4 +633,87 @@ private String getRack() {
}
return null;
}
+
+ public void patchOpenShiftRoutes(OpenShiftClient openShiftClient) {
+ if (openShiftClient == null) {
+ log.debug("OpenShift Routes not supported on this cluster, skipping Route reconciliation");
+ return;
+ }
+
+ Service svc = client.services()
+ .inNamespace(namespace)
+ .withName(resourceName)
+ .get();
+
+ if (svc == null || svc.getSpec() == null || svc.getSpec().getPorts() == null) {
+ log.warnf("Service {} not found or has no ports, skipping Route creation", resourceName);
+ return;
+ }
+
+ for (ServicePort port : svc.getSpec().getPorts()) {
+ patchSingleRoute(openShiftClient, svc, port);
+ }
+ }
+
+ private void patchSingleRoute(OpenShiftClient openShiftClient,
+ Service service,
+ ServicePort port) {
+
+ String routeName = resourceName + "-" + port.getName();
+
+ RouteFluent.SpecNested routeBuilderSpecNested = new RouteBuilder()
+ .withNewMetadata()
+ .withName(routeName)
+ .withNamespace(namespace)
+ .withLabels(getLabels(spec.getLabels()))
+ .endMetadata()
+ .withNewSpec()
+ .withNewTo()
+ .withKind("Service")
+ .withName(service.getMetadata().getName())
+ .endTo()
+ .withNewPort()
+ .withTargetPort(new IntOrString(port.getName()))
+ .endPort();
+
+ applyTlsConfig(routeBuilderSpecNested, port.getName());
+
+ Route desired = routeBuilderSpecNested.endSpec().build();
+
+ openShiftClient.routes()
+ .inNamespace(namespace)
+ .resource(desired).serverSideApply();
+
+ log.infof("Route '%s' reconciled for Service port '%s'",
+ routeName, port.getName());
+ }
+
+ private void applyTlsConfig(RouteFluent.SpecNested routeBuilderSpecNested,
+ String portName) {
+
+ switch (portName) {
+ case "http":
+ case "ws":
+ case "pulsar":
+ case "kafkaplaintext":
+ routeBuilderSpecNested.withNewTls()
+ .withTermination("edge")
+ .withInsecureEdgeTerminationPolicy("Redirect")
+ .endTls();
+ break;
+
+ case "https":
+ case "wss":
+ case "pulsarssl":
+ case "kafkassl":
+ routeBuilderSpecNested.withNewTls()
+ .withTermination("passthrough")
+ .endTls();
+ break;
+
+ default:
+ log.debugf("Port '%s' not exposed via Route (no TLS mapping)", portName);
+ }
+ }
+
}
diff --git a/pom.xml b/pom.xml
index c7e7aa47..4b5148b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,6 +89,11 @@
pom
import
+
+ io.fabric8
+ openshift-client
+ ${fabric8.version}
+
commons-codec
commons-codec