Skip to content

Commit

Permalink
Merge pull request #429 from res0nance/null-slavetemplate
Browse files Browse the repository at this point in the history
Handle cases where SlaveTemplate has been removed
  • Loading branch information
Raihaan Shouhell committed Feb 14, 2020
2 parents 69a4b31 + 377f68e commit 6ad20f0
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 22 deletions.
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>3.55</version>
<version>3.56</version>
<relativePath/>
</parent>

<artifactId>ec2</artifactId>
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/hudson/plugins/ec2/EC2Cloud.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.domains.Domain;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import hudson.plugins.ec2.util.AmazonEC2Factory;
import hudson.security.ACL;

Expand Down Expand Up @@ -64,6 +62,7 @@
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import javax.annotation.CheckForNull;
import javax.servlet.ServletException;

import hudson.Extension;
Expand Down Expand Up @@ -285,6 +284,7 @@ public List<SlaveTemplate> getTemplates() {
return Collections.unmodifiableList(templates);
}

@CheckForNull
public SlaveTemplate getTemplate(String template) {
for (SlaveTemplate t : templates) {
if (t.description.equals(template)) {
Expand Down Expand Up @@ -799,7 +799,7 @@ public static AWSCredentialsProvider createCredentialsProvider(
}

@CheckForNull
private static AmazonWebServicesCredentials getCredentials(@Nullable String credentialsId) {
private static AmazonWebServicesCredentials getCredentials(@CheckForNull String credentialsId) {
if (StringUtils.isBlank(credentialsId)) {
return null;
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/hudson/plugins/ec2/EC2Computer.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public EC2Cloud getCloud() {
return node == null ? null : node.getCloud();
}

@CheckForNull
public SlaveTemplate getSlaveTemplate() {
EC2AbstractSlave node = getNode();
if (node != null) {
Expand Down
23 changes: 14 additions & 9 deletions src/main/java/hudson/plugins/ec2/ssh/EC2UnixLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,16 @@ protected void launchScript(EC2Computer computer, TaskListener listener) throws
boolean successful = false;
PrintStream logger = listener.getLogger();
EC2AbstractSlave node = computer.getNode();
SlaveTemplate template = computer.getSlaveTemplate();

if(node == null) {
throw new IllegalStateException();
}

if (template == null) {
throw new IOException("Could not find corresponding slave template for " + computer.getDisplayName());
}

if (node instanceof EC2Readiness) {
EC2Readiness readinessNode = (EC2Readiness) node;
int tries = readinessTries;
Expand All @@ -152,11 +157,11 @@ protected void launchScript(EC2Computer computer, TaskListener listener) throws
logInfo(computer, listener, "Launching instance: " + node.getInstanceId());

try {
boolean isBootstrapped = bootstrap(computer, listener);
boolean isBootstrapped = bootstrap(computer, listener, template);
if (isBootstrapped) {
// connect fresh as ROOT
logInfo(computer, listener, "connect fresh as root");
cleanupConn = connectToSsh(computer, listener);
cleanupConn = connectToSsh(computer, listener, template);
KeyPair key = computer.getCloud().getKeyPair();
if (!cleanupConn.authenticateWithPublicKey(computer.getRemoteAdmin(), key.getKeyMaterial().toCharArray(), "")) {
logWarning(computer, listener, "Authentication failed");
Expand Down Expand Up @@ -240,7 +245,7 @@ protected void launchScript(EC2Computer computer, TaskListener listener) throws

try {
// Obviously the master must have an installed ssh client.
String sshClientLaunchString = String.format("ssh -o StrictHostKeyChecking=no -i %s %s@%s -p %d %s", identityKeyFile.getAbsolutePath(), node.remoteAdmin, getEC2HostAddress(computer), node.getSshPort(), launchString);
String sshClientLaunchString = String.format("ssh -o StrictHostKeyChecking=no -i %s %s@%s -p %d %s", identityKeyFile.getAbsolutePath(), node.remoteAdmin, getEC2HostAddress(computer, template), node.getSshPort(), launchString);

logInfo(computer, listener, "Launching remoting agent (via SSH client process): " + sshClientLaunchString);
CommandLauncher commandLauncher = new CommandLauncher(sshClientLaunchString, null);
Expand Down Expand Up @@ -308,7 +313,7 @@ private File createIdentityKeyFile(EC2Computer computer) throws IOException {
}
}

private boolean bootstrap(EC2Computer computer, TaskListener listener) throws IOException,
private boolean bootstrap(EC2Computer computer, TaskListener listener, SlaveTemplate template) throws IOException,
InterruptedException, AmazonClientException {
logInfo(computer, listener, "bootstrap()");
Connection bootstrapConn = null;
Expand All @@ -322,7 +327,7 @@ private boolean bootstrap(EC2Computer computer, TaskListener listener) throws IO
while (tries-- > 0) {
logInfo(computer, listener, "Authenticating as " + computer.getRemoteAdmin());
try {
bootstrapConn = connectToSsh(computer, listener);
bootstrapConn = connectToSsh(computer, listener, template);
isAuthenticated = bootstrapConn.authenticateWithPublicKey(computer.getRemoteAdmin(), key.getKeyMaterial().toCharArray(), "");
} catch(IOException e) {
logException(computer, listener, "Exception trying to authenticate", e);
Expand All @@ -346,7 +351,7 @@ private boolean bootstrap(EC2Computer computer, TaskListener listener) throws IO
return true;
}

private Connection connectToSsh(EC2Computer computer, TaskListener listener) throws AmazonClientException,
private Connection connectToSsh(EC2Computer computer, TaskListener listener, SlaveTemplate template) throws AmazonClientException,
InterruptedException {
final EC2AbstractSlave node = computer.getNode();
final long timeout = node == null ? 0L : node.getLaunchTimeoutInMillis();
Expand All @@ -359,7 +364,7 @@ private Connection connectToSsh(EC2Computer computer, TaskListener listener) thr
+ " seconds of waiting for ssh to become available. (maximum timeout configured is "
+ (timeout / 1000) + ")");
}
String host = getEC2HostAddress(computer);
String host = getEC2HostAddress(computer, template);

if ((node instanceof EC2SpotSlave) && computer.getInstanceId() == null) {
// getInstanceId() on EC2SpotSlave can return null if the spot request doesn't yet know
Expand Down Expand Up @@ -411,9 +416,9 @@ public boolean verifyServerHostKey(String hostname, int port, String serverHostK
}
}

private String getEC2HostAddress(EC2Computer computer) throws InterruptedException {
private static String getEC2HostAddress(EC2Computer computer, SlaveTemplate template) throws InterruptedException {
Instance instance = computer.updateInstanceDescription();
ConnectionStrategy strategy = computer.getSlaveTemplate().connectionStrategy;
ConnectionStrategy strategy = template.connectionStrategy;
return EC2HostAddressProvider.unix(instance, strategy);
}

Expand Down
22 changes: 13 additions & 9 deletions src/main/java/hudson/plugins/ec2/win/EC2WindowsLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import hudson.plugins.ec2.EC2Computer;
import hudson.plugins.ec2.EC2ComputerLauncher;
import hudson.plugins.ec2.EC2HostAddressProvider;
import hudson.plugins.ec2.SlaveTemplate;
import hudson.plugins.ec2.win.winrm.WindowsProcess;
import hudson.remoting.Channel;
import hudson.remoting.Channel.Listener;
Expand All @@ -19,6 +20,8 @@
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nonnull;

import jenkins.model.Jenkins;
import org.apache.commons.io.IOUtils;

Expand All @@ -36,12 +39,17 @@ public class EC2WindowsLauncher extends EC2ComputerLauncher {
protected void launchScript(EC2Computer computer, TaskListener listener) throws IOException,
AmazonClientException, InterruptedException {
final PrintStream logger = listener.getLogger();
final WinConnection connection = connectToWinRM(computer, logger);
EC2AbstractSlave node = computer.getNode();
if (node == null || connection == null) {
if (node == null) {
logger.println("Unable to fetch node information");
return;
}
final SlaveTemplate template = computer.getSlaveTemplate();
if (template == null) {
throw new IOException("Could not find corresponding slave template for " + computer.getDisplayName());
}

final WinConnection connection = connectToWinRM(computer, node, template, logger);

try {
String initScript = node.initScript;
Expand Down Expand Up @@ -104,13 +112,9 @@ public void onClosed(Channel channel, IOException cause) {
}
}

private WinConnection connectToWinRM(EC2Computer computer, PrintStream logger) throws AmazonClientException,
@Nonnull
private WinConnection connectToWinRM(EC2Computer computer, EC2AbstractSlave node, SlaveTemplate template, PrintStream logger) throws AmazonClientException,
InterruptedException {
EC2AbstractSlave node = computer.getNode();
if (node == null) {
return null;
}

final long minTimeout = 3000;
long timeout = node.getLaunchTimeoutInMillis(); // timeout is less than 0 when jenkins is booting up.
if (timeout < minTimeout) {
Expand All @@ -131,7 +135,7 @@ private WinConnection connectToWinRM(EC2Computer computer, PrintStream logger) t

if (connection == null) {
Instance instance = computer.updateInstanceDescription();
String host = EC2HostAddressProvider.windows(instance, computer.getSlaveTemplate().connectionStrategy);
String host = EC2HostAddressProvider.windows(instance, template.connectionStrategy);

if ("0.0.0.0".equals(host)) {
logger.println("Invalid host 0.0.0.0, your host is most likely waiting for an ip address.");
Expand Down

0 comments on commit 6ad20f0

Please sign in to comment.