Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-59094] Jenkins connection failure with tunneling #345

Merged
merged 9 commits into from
Sep 6, 2019

Conversation

jeffret-b
Copy link
Contributor

See JENKINS-59094

Under some conditions, agents using tunneling have failed to connect after changes in the 3.34 Remoting release. I haven't been able to reproduce it or isolate it yet, but this change restores the host:port parsing logic to previous behavior for handling an empty port. At a minimum, this should at least get us past the exception. It may well solve the problem.

Adjust the logic for parsing the tunneling host:port to match what it used to bebefore the latest release.
@bbara
Copy link

bbara commented Aug 28, 2019

Hi!

I have a pretty similar problem but in my case the HOST is empty.

This line suggests that the tunnel string, on some point in code, is auto-completed:

@Option(name="-tunnel",metaVar="HOST:PORT",
usage="Connect to the specified host and port, instead of connecting directly to Jenkins. " +
"Useful when connection to Jenkins needs to be tunneled. Can be also HOST: or :PORT, " +
"in which case the missing portion will be auto-configured like the default behavior")
public String tunnel;

However, this is not done up to this point, where the failure happens:

int portSeparator = hostPortValue.lastIndexOf(':');
if (portSeparator <= 0) {
throw new IllegalArgumentException("Invalid HOST:PORT value: " + value);
}
host = hostPortValue.substring(0, portSeparator).trim();
if (host.isEmpty()) {
throw new IllegalArgumentException("Invalid HOST:PORT value: " + value);
}

I currently don't have time to investigate into it further, but at some point later in code, there must have happened some kind of auto-completion.

Unfortunately, I also haven't figured out where the tunnel is set at all, because I'm not sure where this jelly is located in the UI.

BR,
BB

Edit: phrasing

Only the separator needs to be provided.
Jenkins magic strikes again.
Copy link
Member

@jvz jvz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM. No manual testing done by myself.

@jeffret-b
Copy link
Contributor Author

This should get the parsing back to the state it was before, which should resolve [JENKINS-59094] and the related issue reported above by @bbara. I haven't been able to reproduce or test these other scenarios. It would be great if someone else with those setups could give it a try.

@bbara
Copy link

bbara commented Aug 28, 2019

I currently have limited access to my Jenkins instance but I will provide feedback asap.

Some more findings:
Help for the JNLP Tunnel
Setting up the tunnel is an advanced configuration
Function to get the ServerName that is actually never called

@bbara
Copy link

bbara commented Aug 29, 2019

Does not work for me:

Aug 29, 2019 9:12:16 AM hudson.remoting.jnlp.Main$CuiListener status
INFO: Handshaking
Aug 29, 2019 9:12:16 AM hudson.remoting.jnlp.Main$CuiListener status
INFO: Connecting to :8000
Aug 29, 2019 9:12:27 AM hudson.remoting.jnlp.Main$CuiListener status
INFO: Connecting to :8000 (retrying:2)
java.io.IOException: Failed to connect to :8000
        at org.jenkinsci.remoting.engine.JnlpAgentEndpoint.open(JnlpAgentEndpoint.java:243)
        at hudson.remoting.Engine.connectTcp(Engine.java:680)
        at hudson.remoting.Engine.innerRun(Engine.java:558)
        at hudson.remoting.Engine.run(Engine.java:490)

So for my case, it seems like the server name/HOST got lost somewhere.

However, I found the advanced setting to configure the tunnel of a node which is, in my setup, not needed anymore anyways.

For Reproduction:
As this setup worked in the last version, simply setting the tunnel of a node to the TCP agent port, which is set in the security settings of Jenkins, should be sufficient. The same should be valid for the HOST part, so simply setting the HOST to the actual server name and omit the actual port number should auto complete it to the one mentioned above.

Pass in the default host and port, which might be obtained from headers or other means.
@jeffret-b
Copy link
Contributor Author

Thanks to @bbara for the suggestion on how to configure this for testing I was able to make some progress and figure out at least some of the Jenkins magic going on here. I tweaked the PR to handle those cases. I've tested it out with no tunnel set and with it set to values like "hostname:port", "hostname:", ":port", and even ":". (The latter doesn't do anything useful that I know of, but kind of exists to support the others.)

I feel better after being able to reproduce at least some of the problems, at least in a simplified case.

Any other reviews and testing would be welcome. I'm hopeful this is ready to go.

Co-Authored-By: Matt Sicker <boards@gmail.com>
Copy link
Member

@jvz jvz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated changes look good. Since last time, I did discover that Jetty has their own class fairly similar to this if you want inspiration: https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java

Co-Authored-By: Matt Sicker <boards@gmail.com>
Copy link
Member

@oleg-nenashev oleg-nenashev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you break the APi anyway, would be nice to ensure proper error propagation without runtime exceptions so that we do not hit other regressions later

host = hostValue.length() > 0 ? hostValue : defaultHost;
String portString = hostPortValue.substring(portSeparator + 1).trim();
if (portString.length() > 0) {
port = Integer.parseInt(portString);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unhandled NumberFormatException

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NumberFormatException was unhandled in prior versions as well. I checked it by running 3.33 (before any of these changes) with a port value that is not a number. The agent fails on startup with the NumberFormatException.

Do you think we should change that behavior here now? Should it throw a different exception? Or log and ignore the error?

@jeffret-b
Copy link
Contributor Author

@oleg-nenashev, could you please take a look again?

@jeffret-b jeffret-b added regression-fix Pull request that fixes a regression in one of the previous Jenkins releases ready-to-merge labels Sep 6, 2019
@jeffret-b jeffret-b merged commit 69618d1 into jenkinsci:master Sep 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-to-merge regression-fix Pull request that fixes a regression in one of the previous Jenkins releases
Projects
None yet
4 participants