diff --git a/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnectionProvider.java b/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnectionProvider.java index b127f0e86..5ab4357cd 100644 --- a/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnectionProvider.java +++ b/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnectionProvider.java @@ -6,14 +6,13 @@ import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorProvider; import javax.management.remote.JMXServiceURL; -import org.jolokia.client.jmxadapter.JolokiaJmxConnector; /** * This provides support for handling JMX urls over the Jolokia protocol to JVMs running in kubernetes pods * Syntax examples * * * Regular expressions in service url is supported so you can have working URLs across deploys. @@ -27,7 +26,7 @@ * Example: * //NB: include trailing slash to jolokia endpoint * JMXConnector connector = JMXConnectorFactory - * .connect(new JMXServiceURL("service:jmx:kubernetes:///api/v1/namespaces/mynamespace/pods/mypodname-.+/actuator/jolokia/"))); + * .connect(new JMXServiceURL("service:jmx:kubernetes:///namespaces/mynamespace/pods/mypodname-.+/actuator/jolokia/"))); * connector.connect(); * connector.getMBeanServerConnection(); * diff --git a/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnector.java b/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnector.java index 3a6f27688..f6afbe4de 100644 --- a/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnector.java +++ b/client/kubernetes/src/main/java/org/jolokia/kubernetes/client/KubernetesJmxConnector.java @@ -7,9 +7,7 @@ import io.kubernetes.client.Configuration; import io.kubernetes.client.Pair; import io.kubernetes.client.apis.CoreV1Api; -import io.kubernetes.client.models.V1OwnerReference; import io.kubernetes.client.models.V1Pod; -import io.kubernetes.client.models.V1Service; import io.kubernetes.client.util.ClientBuilder; import io.kubernetes.client.util.KubeConfig; import java.io.FileReader; @@ -23,16 +21,13 @@ import javax.management.remote.JMXConnector; import javax.management.remote.JMXServiceURL; import org.jolokia.client.J4pClient; -import org.jolokia.client.J4pClientBuilderFactory; import org.jolokia.client.jmxadapter.JolokiaJmxConnector; import org.jolokia.client.jmxadapter.RemoteJmxAdapter; public class KubernetesJmxConnector extends JolokiaJmxConnector { private static Pattern POD_PATTERN = Pattern - .compile("/api/v1/namespaces/([^/]+)/pods/([^/]+)/proxy/(.+)"); - private static Pattern SERVICE_PATTERN = Pattern - .compile("/api/v1/namespaces/([^/]+)/services/([^/]+)/proxy/(.+)"); + .compile("/namespaces/([^/]+)/pods/([^/]+)/(.+)"); private static ApiClient apiClient; public KubernetesJmxConnector(JMXServiceURL serviceURL, @@ -43,7 +38,9 @@ public KubernetesJmxConnector(JMXServiceURL serviceURL, @Override public void connect(Map env) throws IOException { if (!"kubernetes".equals(this.serviceUrl.getProtocol())) { - throw new MalformedURLException(String.format("Invalid URL %s : Only protocol \"kubernetes\" is supported (not %s)", serviceUrl, serviceUrl.getProtocol())); + throw new MalformedURLException(String + .format("Invalid URL %s : Only protocol \"kubernetes\" is supported (not %s)", serviceUrl, + serviceUrl.getProtocol())); } final Map mergedEnvironment = this.mergedEnvironment(env); ApiClient client = getApiClient(mergedEnvironment); @@ -57,7 +54,7 @@ protected RemoteJmxAdapter createAdapter(J4pClient client) throws IOException { } public static ApiClient getApiClient(Map env) throws IOException { - if(apiClient != null){ + if (apiClient != null) { return apiClient; } return buildApiClient(env); @@ -80,102 +77,45 @@ public static ApiClient buildApiClient(Map env) throws IOException { protected J4pClient expandAndProbeUrl(ApiClient client, Map env) throws MalformedURLException { Configuration.setDefaultApiClient(client); - CoreV1Api api = new CoreV1Api(); String proxyPath = this.serviceUrl.getURLPath(); + J4pClient connection; final HashMap headersForProbe = createHeadersForProbe(env); try { - if (SERVICE_PATTERN.matcher(proxyPath).matches()) { - final Matcher matcher = SERVICE_PATTERN.matcher(proxyPath); - if (matcher.find()) { - String namespacePattern = matcher.group(1); - String servicePattern = matcher.group(); - String actualNamespace = null; - String actualName = null; - for (final V1Service service : api - .listServiceForAllNamespaces(null, null, false, null, null, null, null, 5, null) - .getItems()) { - - if (service.getMetadata().getNamespace().matches(namespacePattern) && service - .getMetadata().getName().matches(servicePattern)) { - actualNamespace = service.getMetadata().getNamespace(); - actualName = service.getMetadata().getName(); - } - } - if (actualName == null || actualNamespace == null) { - throw new MalformedURLException( - "Coult not find service in cluster for pattern " + proxyPath); - } - if (!actualNamespace.equals(namespacePattern)) { - proxyPath = proxyPath.replace(namespacePattern, actualNamespace); - } - if (!actualName.equals(servicePattern)) { - proxyPath = proxyPath.replace(servicePattern, actualName); - } - //probe a request to this URL via proxy - try { - final Response response = probeProxyPath(client, proxyPath, - headersForProbe); - response.body().close(); - if (response.isSuccessful()) { - return new J4pClient( - proxyPath, new MinimalHttpClientAdapter(client, proxyPath, env)); - } - } catch (IOException ignore) { - } - //try to fall back to finding a pod to see if we are more successful connecting to it, will be picked up from next if block if successful - - String path = matcher.group(3); - proxyPath = findPodPathIfAnyForService(actualName, actualNamespace, path, api); - - - } - } if (POD_PATTERN.matcher(proxyPath).matches()) { final Matcher matcher = POD_PATTERN.matcher(proxyPath); if (matcher.find()) { - String namespacePattern = matcher.group(1); - + String namespace = matcher.group(1); String podPattern = matcher.group(2); - String actualNamespace = null; - String actualPodName = null; - for (final V1Pod pod : api - .listPodForAllNamespaces(null, null, false, null, null, null, null, 5, null) - .getItems()) { - - if (pod.getMetadata().getNamespace().matches(namespacePattern) && pod.getMetadata() - .getName().matches(podPattern)) { - actualNamespace = pod.getMetadata().getNamespace(); - actualPodName = pod.getMetadata().getName(); - break; - } - } - if (actualPodName == null || actualNamespace == null) { - throw new MalformedURLException( - "Could not find pod in cluster for pattern " + proxyPath); - } - if (!actualNamespace.equals(namespacePattern)) { - proxyPath = proxyPath.replace(namespacePattern, actualNamespace); - } - if (!actualPodName.equals(podPattern)) { - proxyPath = proxyPath.replace(podPattern, actualPodName); - } - //probe a request to this URL via proxy - try { - final Response response = probeProxyPath(client, proxyPath, - headersForProbe); - response.body().close(); - if (response.isSuccessful()) { - return new J4pClient( - proxyPath, new MinimalHttpClientAdapter(client, proxyPath, env)); + String path = matcher.group(3); + //check if podname pans out directly + if ((connection = probeProxyPath(env, client, namespace, podPattern, path, + headersForProbe)) != null) { + return connection; + } else { //scan through pods in namespace if podname is a pattern + for (final V1Pod pod : api + .listNamespacedPod(namespace, + false, + null, + null, + null, + null, + null, + null, + 10, + null) + .getItems()) { + if (pod.getMetadata().getNamespace().matches(namespace) && pod.getMetadata() + .getName().matches(podPattern)) { + if ((connection = probeProxyPath(env, client, namespace, + pod.getMetadata().getName(), path, headersForProbe)) != null) { + return connection; + } + } } - - } catch (IOException ignore) { } } - } - } catch (ApiException ignore) { } throw new MalformedURLException("Unable to connect to proxypath " + proxyPath); @@ -184,46 +124,35 @@ protected J4pClient expandAndProbeUrl(ApiClient client, private HashMap createHeadersForProbe( Map env) { final HashMap headers = new HashMap(); - String[] credentials= (String[]) env.get(JMXConnector.CREDENTIALS); - if(credentials != null) { + String[] credentials = (String[]) env.get(JMXConnector.CREDENTIALS); + if (credentials != null) { headers.put("Authorization", Credentials.basic(credentials[0], credentials[1])); } return headers; } /** - * Find a pod of a service, fail if none + * Probe whether we find Jolokia in given namespace, pod and path */ - private String findPodPathIfAnyForService(String actualName, String actualNamespace, String path, - CoreV1Api api) throws MalformedURLException { + public static J4pClient probeProxyPath(Map env, ApiClient client, + String namespace, String podName, String path, + HashMap headers) + throws ApiException { + + final String proxyPath = String + .format("/api/v1/namespaces/%s/pods/%s/proxy/%s", namespace, podName, path); try { - for (V1Pod pod : api - .listNamespacedPod(actualNamespace, false, null, null, null, null, null, null, 5, false) - .getItems()) { - for (V1OwnerReference ref : pod.getMetadata().getOwnerReferences()) { - //pod that references the service - if (ref.getName().equals(actualName)) { - return String - .format("/api/v1/namespaces/%s/pods/%s/proxy/%s", actualNamespace, actualName, - path); - } - } + Response response = MinimalHttpClientAdapter + .performRequest(client, proxyPath, Collections.singletonMap("type", "version"), + Collections.emptyList(), "POST", headers); + + response.body().close(); + if (response.isSuccessful()) { + return new J4pClient( + proxyPath, new MinimalHttpClientAdapter(client, proxyPath, env)); } - } catch (ApiException ignore) { + } catch (IOException ignore) { } - - throw new MalformedURLException(String - .format("Could not find any pod of service %s in namespace %s with path %s", actualName, - actualNamespace, path)); - } - - /** - */ - public static Response probeProxyPath(ApiClient client, String proxyPath, - HashMap headers) - throws IOException, ApiException { - return MinimalHttpClientAdapter - .performRequest(client, proxyPath, Collections.singletonMap("type", "version"), - Collections.emptyList(), "POST", headers); + return null; } } diff --git a/client/kubernetes/src/test/java/org/jolokia/kubernetes/client/ManualTestConnection.java b/client/kubernetes/src/test/java/org/jolokia/kubernetes/client/ManualTestConnection.java index b1c4e671c..3871a735d 100644 --- a/client/kubernetes/src/test/java/org/jolokia/kubernetes/client/ManualTestConnection.java +++ b/client/kubernetes/src/test/java/org/jolokia/kubernetes/client/ManualTestConnection.java @@ -11,7 +11,7 @@ public class ManualTestConnection { @Test(groups = "manual") public void testConnect() throws IOException { final JMXServiceURL jmxServiceURL = new JMXServiceURL( - "service:jmx:kubernetes:///api/v1/namespaces/che/pods/workspace.+tools-.+-.+/proxy/manage/jolokia/" + "service:jmx:kubernetes:///namespaces/che/pods/workspace.+tools-.+-.+/manage/jolokia/" ); jmxServiceURL.getProtocol();