From ecefcc75ecee7c188aff19d0dfdc3c5b247a587a Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Wed, 9 Nov 2016 15:00:23 +0100 Subject: [PATCH 1/2] [JENKINS-39617] - JnlpAgentEndpointResolver should not fail if one of the URLs is malformed --- .../remoting/engine/JnlpAgentEndpointResolver.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java index 5ba2bda58..04e9ca5fd 100644 --- a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java +++ b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java @@ -127,7 +127,16 @@ public void setTunnel(String tunnel) { public JnlpAgentEndpoint resolve() throws IOException { IOException firstError = null; for (String jenkinsUrl : jenkinsUrls) { - URL salURL = toAgentListenerURL(jenkinsUrl); + + final URL selectedJenkinsURL; + final URL salURL; + try { + selectedJenkinsURL = new URL(jenkinsUrl); + salURL = toAgentListenerURL(jenkinsUrl); + } catch (MalformedURLException ex) { + LOGGER.log(Level.WARNING, String.format("Cannot parse agent endpoint URL %s. Skipping it", jenkinsUrl), ex); + continue; + } // find out the TCP port HttpURLConnection con = From 837bfeb81e8ed360e8350711b59fb8d9f3311882 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Wed, 9 Nov 2016 15:01:47 +0100 Subject: [PATCH 2/2] [JENKINS-39596] - Restore assigning of hudsonUrl in hudson.remoting.Engine It's a regression in remotirn-3.0 --- src/main/java/hudson/remoting/Engine.java | 8 +++++ .../remoting/engine/JnlpAgentEndpoint.java | 32 ++++++++++++++++++- .../engine/JnlpAgentEndpointResolver.java | 3 +- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/main/java/hudson/remoting/Engine.java b/src/main/java/hudson/remoting/Engine.java index 96a2b11a2..15484e12d 100644 --- a/src/main/java/hudson/remoting/Engine.java +++ b/src/main/java/hudson/remoting/Engine.java @@ -128,6 +128,7 @@ public void run() { * This value is determined from {@link #candidateUrls} after a successful connection. * Note that this URL DOES NOT have "tcpSlaveAgentListener" in it. */ + @CheckForNull private URL hudsonUrl; private final String secretKey; @@ -171,6 +172,12 @@ public void setJarCache(JarCache jarCache) { this.jarCache = jarCache; } + /** + * Provides Jenkins URL if available. + * @return Jenkins URL. May return {@code null} if the connection is not established or if the URL cannot be determined + * in the {@link JnlpAgentEndpointResolver}. + */ + @CheckForNull public URL getHudsonUrl() { return hudsonUrl; } @@ -334,6 +341,7 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) { events.status("Could not resolve server among " + candidateUrls); return; } + hudsonUrl = endpoint.getServiceUrl(); events.status(String.format("Agent discovery successful%n" + " Agent address: %s%n" diff --git a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java index 203b45d9e..af58d7afc 100644 --- a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java +++ b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java @@ -29,6 +29,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.net.URL; import java.nio.channels.SocketChannel; import java.security.interfaces.RSAPublicKey; import java.util.Collections; @@ -65,7 +66,23 @@ public class JnlpAgentEndpoint { */ @CheckForNull private final Set protocols; + + /** + * Jenkins URL for the discovered endpoint. + * @since TODO + */ + @CheckForNull + private final URL serviceUrl; + /** + * @deprecated Use {@link #JnlpAgentEndpoint(java.lang.String, int, java.security.interfaces.RSAPublicKey, java.util.Set, java.lang.String)} + */ + @Deprecated + public JnlpAgentEndpoint(@Nonnull String host, int port, @CheckForNull RSAPublicKey publicKey, + @CheckForNull Set protocols) { + this(host, port, publicKey, protocols, null); + } + /** * Constructor for a remote {@code Jenkins} instance. * @@ -73,9 +90,12 @@ public class JnlpAgentEndpoint { * @param port the port. * @param publicKey the {@code InstanceIdentity.getPublic()} of the remote instance (if known). * @param protocols The supported protocols. + * @param serviceURL URL of the service hosting the remoting endpoint. + * Use {@code null} if it is not a web service or if the URL cannot be determined + * @since TODO */ public JnlpAgentEndpoint(@Nonnull String host, int port, @CheckForNull RSAPublicKey publicKey, - @CheckForNull Set protocols) { + @CheckForNull Set protocols, @CheckForNull URL serviceURL) { if (port <= 0 || 65536 <= port) { throw new IllegalArgumentException("Port " + port + " is not in the range 1-65535"); } @@ -83,6 +103,7 @@ public JnlpAgentEndpoint(@Nonnull String host, int port, @CheckForNull RSAPublic this.port = port; this.publicKey = publicKey; this.protocols = protocols == null ? null : Collections.unmodifiableSet(new LinkedHashSet(protocols)); + this.serviceUrl = serviceURL; } /** @@ -95,6 +116,15 @@ public InetSocketAddress getAddress() { return new InetSocketAddress(host, port); } + /** + * Retrieves URL of the web service providing the remoting endpoint. + * @return Service URL if available. {@code null} otherwise. + */ + @CheckForNull + public URL getServiceUrl() { + return serviceUrl; + } + /** * Gets the hostname. * diff --git a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java index 04e9ca5fd..2984d80d5 100644 --- a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java +++ b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java @@ -232,7 +232,8 @@ public int compare(String o1, String o2) { if (tokens[0].length() > 0) host = tokens[0]; if (tokens[1].length() > 0) port = Integer.parseInt(tokens[1]); } - return new JnlpAgentEndpoint(host, port, identity, agentProtocolNames); + + return new JnlpAgentEndpoint(host, port, identity, agentProtocolNames, selectedJenkinsURL); } finally { con.disconnect(); }