From 2a6dfdb611924faac600afd70cd365069017c2e7 Mon Sep 17 00:00:00 2001 From: sandeep-ctds Date: Wed, 31 Dec 2025 17:08:50 +0530 Subject: [PATCH] openshift routes for proxy --- operator/pom.xml | 4 + .../kaap/controllers/AbstractController.java | 8 ++ .../controllers/proxy/ProxyController.java | 2 + .../proxy/ProxyResourcesFactory.java | 88 +++++++++++++++++++ pom.xml | 5 ++ 5 files changed, 107 insertions(+) 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