Java client for Kubernetes and OpenShift providing access to full REST APIs via a fluent DSL
—
This document covers OpenShift networking operations, including routes, network policies, cluster networking, and network-related resources.
import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.Route;
import io.fabric8.openshift.api.model.RouteList;
import io.fabric8.openshift.api.model.NetNamespace;
import io.fabric8.openshift.api.model.NetNamespaceList;
import io.fabric8.openshift.api.model.ClusterNetwork;
import io.fabric8.openshift.api.model.ClusterNetworkList;
import io.fabric8.openshift.api.model.EgressNetworkPolicy;
import io.fabric8.openshift.api.model.EgressNetworkPolicyList;
import io.fabric8.openshift.api.model.HostSubnet;
import io.fabric8.openshift.api.model.HostSubnetList;
import io.fabric8.openshift.api.model.miscellaneous.cncf.cni.v1.NetworkAttachmentDefinition;
import io.fabric8.openshift.api.model.miscellaneous.cncf.cni.v1.NetworkAttachmentDefinitionList;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;// List all routes in a namespace
RouteList routes = client.routes()
.inNamespace("my-project")
.list();
// Get a specific route
Route route = client.routes()
.inNamespace("my-project")
.withName("my-app")
.get();
// Create a new route
Route newRoute = new RouteBuilder()
.withNewMetadata()
.withName("my-new-app")
.withNamespace("my-project")
.addToLabels("app", "my-new-app")
.endMetadata()
.withNewSpec()
.withHost("my-app.example.com")
.withNewTo()
.withKind("Service")
.withName("my-app-service")
.withWeight(100)
.endTo()
.withNewPort()
.withNewTargetPort(8080)
.endPort()
.endSpec()
.build();
Route created = client.routes()
.inNamespace("my-project")
.create(newRoute);// Create a route with edge TLS termination
Route secureRoute = new RouteBuilder()
.withNewMetadata()
.withName("secure-app")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.withHost("secure-app.example.com")
.withNewTo()
.withKind("Service")
.withName("my-app-service")
.endTo()
.withNewTls()
.withTermination("edge")
.withInsecureEdgeTerminationPolicy("Redirect")
.endTls()
.endSpec()
.build();
// Create route with passthrough TLS
Route passthroughRoute = new RouteBuilder()
.withNewMetadata()
.withName("passthrough-app")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.withHost("passthrough-app.example.com")
.withNewTo()
.withKind("Service")
.withName("secure-service")
.endTo()
.withNewTls()
.withTermination("passthrough")
.endTls()
.endSpec()
.build();
// Create route with re-encrypt TLS
Route reencryptRoute = new RouteBuilder()
.withNewMetadata()
.withName("reencrypt-app")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.withHost("reencrypt-app.example.com")
.withNewTo()
.withKind("Service")
.withName("backend-service")
.endTo()
.withNewTls()
.withTermination("reencrypt")
.withDestinationCACertificate("-----BEGIN CERTIFICATE-----\n...")
.endTls()
.endSpec()
.build();// Create route with custom certificate
Route customCertRoute = new RouteBuilder()
.withNewMetadata()
.withName("custom-cert-app")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.withHost("custom-cert-app.example.com")
.withNewTo()
.withKind("Service")
.withName("my-app-service")
.endTo()
.withNewTls()
.withTermination("edge")
.withCertificate("-----BEGIN CERTIFICATE-----\n...")
.withKey("-----BEGIN PRIVATE KEY-----\n...")
.withCaCertificate("-----BEGIN CERTIFICATE-----\n...")
.endTls()
.endSpec()
.build();// Get route URL
Route route = client.routes()
.inNamespace("my-project")
.withName("my-app")
.get();
String host = route.getSpec().getHost();
String protocol = route.getSpec().getTls() != null ? "https" : "http";
String url = protocol + "://" + host;
// Check route status
List<RouteIngress> ingress = route.getStatus().getIngress();
for (RouteIngress ing : ingress) {
String routerName = ing.getRouterName();
String host = ing.getHost();
List<RouteIngressCondition> conditions = ing.getConditions();
boolean admitted = conditions.stream()
.anyMatch(condition ->
"Admitted".equals(condition.getType()) &&
"True".equals(condition.getStatus()));
}// List all network namespaces (cluster-scoped)
NetNamespaceList netNamespaces = client.netNamespaces().list();
// Get network namespace for a specific project
NetNamespace netns = client.netNamespaces()
.withName("my-project")
.get();
// Update network namespace (e.g., for network isolation)
NetNamespace updated = client.netNamespaces()
.withName("my-project")
.edit(nns -> new NetNamespaceBuilder(nns)
.withNetid(100) // Isolate this namespace
.build());// Isolate a project network
NetNamespace isolated = client.netNamespaces()
.withName("isolated-project")
.edit(nns -> new NetNamespaceBuilder(nns)
.withNetid(nns.getNetid()) // Keep existing netid for isolation
.addToAnnotations("pod.network.openshift.io/multitenant.change-network", "true")
.build());
// Join networks (assign same netid)
NetNamespace project1 = client.netNamespaces().withName("project1").get();
Integer sharedNetid = project1.getNetid();
client.netNamespaces()
.withName("project2")
.edit(nns -> new NetNamespaceBuilder(nns)
.withNetid(sharedNetid) // Same netid allows communication
.build());// Get cluster network configuration
ClusterNetworkList clusterNetworks = client.clusterNetworks().list();
ClusterNetwork clusterNetwork = client.clusterNetworks()
.withName("default")
.get();
String network = clusterNetwork.getNetwork();
String hostSubnetLength = clusterNetwork.getHostsubnetlength().toString();
List<ClusterNetworkEntry> serviceNetworks = clusterNetwork.getServiceNetworks();// List all host subnets
HostSubnetList hostSubnets = client.hostSubnets().list();
// Get host subnet for a specific node
HostSubnet nodeSubnet = client.hostSubnets()
.withName("worker-node-1")
.get();
String subnet = nodeSubnet.getSubnet();
String hostIP = nodeSubnet.getHostIP();// Create egress network policy
EgressNetworkPolicy egressPolicy = new EgressNetworkPolicyBuilder()
.withNewMetadata()
.withName("default-egress-policy")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.addNewEgress()
.withType("Allow")
.withNewTo()
.withCidrSelector("10.0.0.0/8")
.endTo()
.endEgress()
.addNewEgress()
.withType("Deny")
.withNewTo()
.withDnsName("blocked-site.com")
.endTo()
.endEgress()
.endSpec()
.build();
EgressNetworkPolicy created = client.egressNetworkPolicies()
.inNamespace("my-project")
.create(egressPolicy);// Update egress policy to add new rules
EgressNetworkPolicy updated = client.egressNetworkPolicies()
.inNamespace("my-project")
.withName("default-egress-policy")
.edit(policy -> new EgressNetworkPolicyBuilder(policy)
.editSpec()
.addNewEgress()
.withType("Allow")
.withNewTo()
.withDnsName("api.example.com")
.endTo()
.endEgress()
.endSpec()
.build());
// List egress policies
EgressNetworkPolicyList policies = client.egressNetworkPolicies()
.inNamespace("my-project")
.list();// Create network attachment definition for CNI
NetworkAttachmentDefinition netAttach = new NetworkAttachmentDefinitionBuilder()
.withNewMetadata()
.withName("macvlan-network")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.withConfig("{\n" +
" \"cniVersion\": \"0.3.1\",\n" +
" \"name\": \"macvlan-network\",\n" +
" \"type\": \"macvlan\",\n" +
" \"master\": \"eth0\",\n" +
" \"mode\": \"bridge\",\n" +
" \"ipam\": {\n" +
" \"type\": \"host-local\",\n" +
" \"subnet\": \"192.168.1.0/24\",\n" +
" \"rangeStart\": \"192.168.1.100\",\n" +
" \"rangeEnd\": \"192.168.1.200\",\n" +
" \"gateway\": \"192.168.1.1\"\n" +
" }\n" +
"}")
.endSpec()
.build();
NetworkAttachmentDefinition created = client.networkAttachmentDefinitions()
.inNamespace("my-project")
.create(netAttach);// Create pod with additional network attachment
Pod podWithNetworking = new PodBuilder()
.withNewMetadata()
.withName("multi-network-pod")
.withNamespace("my-project")
.addToAnnotations("k8s.v1.cni.cncf.io/networks", "macvlan-network")
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName("app")
.withImage("nginx")
.endContainer()
.endSpec()
.build();// Watch route changes
client.routes()
.inNamespace("my-project")
.watch(new Watcher<Route>() {
@Override
public void eventReceived(Action action, Route route) {
System.out.println("Route " + action + ": " +
route.getMetadata().getName() +
" -> " + route.getSpec().getHost());
}
@Override
public void onClose(WatcherException cause) {
System.out.println("Route watch closed: " + cause.getMessage());
}
});
// Check route connectivity
Route route = client.routes()
.inNamespace("my-project")
.withName("my-app")
.get();
if (route != null && route.getStatus() != null) {
List<RouteIngress> ingresses = route.getStatus().getIngress();
for (RouteIngress ingress : ingresses) {
boolean isAdmitted = ingress.getConditions().stream()
.anyMatch(condition ->
"Admitted".equals(condition.getType()) &&
"True".equals(condition.getStatus()));
System.out.println("Route " + ingress.getHost() +
" admitted by " + ingress.getRouterName() + ": " + isAdmitted);
}
}import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.*;
public class RouteManager {
private final OpenShiftClient client;
public RouteManager(OpenShiftClient client) {
this.client = client;
}
public String exposeService(String namespace, String serviceName,
String hostname, boolean secure) {
Route route = createRoute(namespace, serviceName, hostname, secure);
waitForRouteAdmission(namespace, route.getMetadata().getName());
String protocol = secure ? "https" : "http";
String url = protocol + "://" + route.getSpec().getHost();
System.out.println("Service exposed at: " + url);
return url;
}
private Route createRoute(String namespace, String serviceName,
String hostname, boolean secure) {
RouteBuilder routeBuilder = new RouteBuilder()
.withNewMetadata()
.withName(serviceName + "-route")
.withNamespace(namespace)
.addToLabels("app", serviceName)
.endMetadata()
.withNewSpec()
.withHost(hostname)
.withNewTo()
.withKind("Service")
.withName(serviceName)
.withWeight(100)
.endTo();
if (secure) {
routeBuilder.editSpec()
.withNewTls()
.withTermination("edge")
.withInsecureEdgeTerminationPolicy("Redirect")
.endTls()
.endSpec();
}
Route route = routeBuilder.build();
return client.routes()
.inNamespace(namespace)
.createOrReplace(route);
}
private void waitForRouteAdmission(String namespace, String routeName) {
client.routes()
.inNamespace(namespace)
.withName(routeName)
.waitUntilCondition(route -> {
if (route.getStatus() == null || route.getStatus().getIngress() == null) {
return false;
}
return route.getStatus().getIngress().stream()
.anyMatch(ingress ->
ingress.getConditions().stream()
.anyMatch(condition ->
"Admitted".equals(condition.getType()) &&
"True".equals(condition.getStatus())));
}, 2, TimeUnit.MINUTES);
}
public void setupNetworkIsolation(String namespace1, String namespace2,
boolean allowCommunication) {
if (allowCommunication) {
// Join network namespaces
NetNamespace ns1 = client.netNamespaces().withName(namespace1).get();
Integer netid = ns1.getNetid();
client.netNamespaces()
.withName(namespace2)
.edit(nns -> new NetNamespaceBuilder(nns)
.withNetid(netid)
.build());
} else {
// Isolate network namespaces
client.netNamespaces()
.withName(namespace1)
.edit(nns -> new NetNamespaceBuilder(nns)
.withNetid(nns.getNetid()) // Keep unique netid
.build());
client.netNamespaces()
.withName(namespace2)
.edit(nns -> new NetNamespaceBuilder(nns)
.withNetid(nns.getNetid()) // Keep unique netid
.build());
}
}
}public class NetworkSecurityManager {
private final OpenShiftClient client;
public NetworkSecurityManager(OpenShiftClient client) {
this.client = client;
}
public void setupEgressPolicies(String namespace) {
// Allow internal cluster communication
EgressNetworkPolicy internalPolicy = new EgressNetworkPolicyBuilder()
.withNewMetadata()
.withName("allow-internal")
.withNamespace(namespace)
.endMetadata()
.withNewSpec()
// Allow cluster internal networks
.addNewEgress()
.withType("Allow")
.withNewTo()
.withCidrSelector("10.0.0.0/8")
.endTo()
.endEgress()
.addNewEgress()
.withType("Allow")
.withNewTo()
.withCidrSelector("172.16.0.0/12")
.endTo()
.endEgress()
.addNewEgress()
.withType("Allow")
.withNewTo()
.withCidrSelector("192.168.0.0/16")
.endTo()
.endEgress()
// Allow DNS
.addNewEgress()
.withType("Allow")
.withNewTo()
.withDnsName("*.cluster.local")
.endTo()
.endEgress()
// Allow specific external services
.addNewEgress()
.withType("Allow")
.withNewTo()
.withDnsName("api.github.com")
.endTo()
.endEgress()
// Deny all other external traffic
.addNewEgress()
.withType("Deny")
.withNewTo()
.withCidrSelector("0.0.0.0/0")
.endTo()
.endEgress()
.endSpec()
.build();
client.egressNetworkPolicies()
.inNamespace(namespace)
.createOrReplace(internalPolicy);
}
}public class Route implements HasMetadata {
public ObjectMeta getMetadata();
public RouteSpec getSpec();
public RouteStatus getStatus();
}
public class RouteSpec {
public String getHost();
public String getSubdomain();
public RouteTargetReference getTo();
public List<RouteTargetReference> getAlternateBackends();
public RoutePort getPort();
public TLSConfig getTls();
public String getWildcardPolicy(); // None, Subdomain
}
public class RouteStatus {
public List<RouteIngress> getIngress();
}
public class RouteIngress {
public String getHost();
public String getRouterName();
public List<RouteIngressCondition> getConditions();
public String getWildcardPolicy();
public String getRouterCanonicalHostname();
}
public class TLSConfig {
public String getTermination(); // edge, passthrough, reencrypt
public String getCertificate();
public String getKey();
public String getCaCertificate();
public String getDestinationCACertificate();
public String getInsecureEdgeTerminationPolicy(); // Allow, Disable, Redirect
}public class NetNamespace implements HasMetadata {
public ObjectMeta getMetadata();
public Integer getNetid();
public List<String> getEgressIPs();
}public class ClusterNetwork implements HasMetadata {
public ObjectMeta getMetadata();
public String getNetwork();
public Integer getHostsubnetlength();
public List<ClusterNetworkEntry> getServiceNetworks();
public String getPluginName();
}public class EgressNetworkPolicy implements HasMetadata {
public ObjectMeta getMetadata();
public EgressNetworkPolicySpec getSpec();
}
public class EgressNetworkPolicySpec {
public List<EgressNetworkPolicyRule> getEgress();
}
public class EgressNetworkPolicyRule {
public String getType(); // Allow, Deny
public EgressNetworkPolicyPeer getTo();
}
public class EgressNetworkPolicyPeer {
public String getCidrSelector();
public String getDnsName();
}public class NetworkAttachmentDefinition implements HasMetadata {
public ObjectMeta getMetadata();
public NetworkAttachmentDefinitionSpec getSpec();
}
public class NetworkAttachmentDefinitionSpec {
public String getConfig(); // CNI configuration JSON
}Install with Tessl CLI
npx tessl i tessl/maven-io-fabric8--kubernetes-client-project