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

More plugin cleanup #220

Merged
merged 2 commits into from Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 22 additions & 23 deletions README.md
@@ -1,14 +1,14 @@
# Swarm
# Swarm Plugin

[![Build Status](https://ci.jenkins.io/buildStatus/icon?job=Plugins/swarm-plugin/master)](https://ci.jenkins.io/job/Plugins/job/swarm-plugin/job/master/)
[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/swarm.svg)](https://plugins.jenkins.io/swarm/)
[![GitHub Release](https://img.shields.io/github/release/jenkinsci/swarm-plugin.svg?label=changelog)](https://github.com/jenkinsci/swarm-plugin/releases/latest)
[![Jenkins Plugin Installs](https://img.shields.io/jenkins/plugin/i/swarm.svg?color=blue)](https://plugins.jenkins.io/swarm/)
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=jenkinsci/swarm-plugin)](https://dependabot.com)

Swarm enables nodes to join a nearby Jenkins master, thereby forming an
ad-hoc cluster. This plugin makes it easier to scale a Jenkins cluster
by spinning up and tearing down new nodes.
The Swarm plugin enables nodes to join a nearby Jenkins master, thereby
forming an ad-hoc cluster. This plugin makes it easier to scale a Jenkins
cluster by spinning up and tearing down new nodes.

This plugin consists of two pieces:

Expand Down Expand Up @@ -42,27 +42,26 @@ settings unexpectedly.

```
$ java -jar swarm-client.jar --help
-deleteExistingClients : Deletes any existing slave with the
-deleteExistingClients : Delete any existing agent with the
same name. (default: false)
-description VAL : Description to be put on the slave
-disableClientsUniqueId : Disables client's unique ID.
(default: false)
-disableSslVerification : Disables SSL verification in the
HttpClient. (default: false)
-description VAL : Description to be put on the agent.
-disableClientsUniqueId : Disable client's unique ID. (default:
false)
-disableSslVerification : Disable SSL verification in the HTTP
client. (default: false)
-disableWorkDir : Disable Remoting working directory
support and run the agent in legacy
mode. (default: false)
-e (--env) : An environment variable to be defined
on this slave. It is specified as
on this agent. It is specified as
'key=value'. Multiple variables are
allowed.
-executors N : Number of executors (default: number
of CPUs)
-failIfWorkDirIsMissing : Fail if the requested Remoting
working directory or internal
directory is missing. (default: false)
-fsroot FILE : Directory where Jenkins places files
(default: .)
-fsroot FILE : Remote root directory. (default: .)
-help (--help) : Show the help screen (default: true)
-internalDir FILE : The name of the directory within the
Remoting working directory where
Expand All @@ -71,7 +70,7 @@ $ java -jar swarm-client.jar --help
-jar-cache FILE : Cache directory that stores JAR files
sent from the master.
-labels VAL : Whitespace-separated list of labels
to be assigned for this slave.
to be assigned for this agent.
Multiple options are allowed.
-labelsFile VAL : File location with space delimited
list of labels. If the file changes,
Expand All @@ -82,13 +81,13 @@ $ java -jar swarm-client.jar --help
seconds. Default is 60 seconds.
(default: 60)
-mode MODE : The mode controlling how Jenkins
allocates jobs to slaves. Can be
either 'normal' (utilize this slave
as much as possible) or 'exclusive'
(leave this machine for tied jobs
only). Default is 'normal'. (default:
normal)
-name VAL : Name of the slave
allocates jobs to agents. Can be
either 'normal' (use this node as
much as possible) or 'exclusive'
(only build jobs with label
expressions matching this node).
Default is 'normal'. (default: normal)
-name VAL : Name of the agent.
-noRetryAfterConnected : Do not retry if a successful
connection gets closed. (default:
false)
Expand Down Expand Up @@ -123,8 +122,8 @@ $ java -jar swarm-client.jar --help
custom fingerprints! Multiple options
are allowed. (default: )
-t (--toolLocation) : A tool location to be defined on this
slave. It is specified as
'toolName=location'
agent. It is specified as
'toolName=location'.
-tunnel VAL : Connect to the specified host and
port, instead of connecting directly
to Jenkins. Useful when connection to
Expand Down
2 changes: 1 addition & 1 deletion client/pom.xml
Expand Up @@ -11,7 +11,7 @@
<artifactId>swarm-client</artifactId>
<groupId>org.jenkins-ci.plugins</groupId>
<packaging>jar</packaging>
<name>Jenkins Swarm Plugin Client</name>
<name>Swarm Client</name>
<version>3.22-SNAPSHOT</version>

<scm>
Expand Down
37 changes: 19 additions & 18 deletions client/src/main/java/hudson/plugins/swarm/Client.java
Expand Up @@ -103,25 +103,26 @@ public static void main(String... args) throws InterruptedException, IOException
.trim();
}


// Only look up the hostname if we have not already specified
// name of the slave. Also in certain cases this lookup might fail.
// E.g.
// Querying a external DNS server which might not be informed
// of a newly created slave from a DHCP server.
//
// From https://docs.oracle.com/javase/8/docs/api/java/net/InetAddress.html#getCanonicalHostName--
//
// "Gets the fully qualified domain name for this IP
// address. Best effort method, meaning we may not be able to
// return the FQDN depending on the underlying system
// configuration."
/*
* Only look up the hostname if we have not already specified name of the agent. In certain
* cases this lookup might fail (e.g., querying an external DNS server which might not be
* informed of a newly created agent from a DHCP server).
*
* From https://docs.oracle.com/javase/8/docs/api/java/net/InetAddress.html#getCanonicalHostName--
*
* "Gets the fully qualified domain name for this IP address. Best effort method, meaning we
* may not be able to return the FQDN depending on the underlying system configuration."
*/
if (options.name == null) {
try {
client.options.name = InetAddress.getLocalHost().getCanonicalHostName();
} catch (IOException e) {
logger.severe("Failed to lookup the canonical hostname of this slave, please check system settings.");
logger.severe("If not possible to resolve please specify a node name using the '-name' option");
logger.severe(
"Failed to look up the canonical hostname of this agent. Check the system"
+ " DNS settings.");
logger.severe(
"If it is not possible to resolve this host, specify a name using the"
+ " \"-name\" option.");
System.exit(1);
}
}
Expand Down Expand Up @@ -159,16 +160,16 @@ public void run(SwarmClient swarmClient, String... args) throws InterruptedExcep
+ swarmClient.getHash());

/*
* Create a new swarm slave. After this method returns, the value of the name field
* Create a new Swarm agent. After this method returns, the value of the name field
* has been set to the name returned by the server, which may or may not be the name
* we originally requested.
*/
swarmClient.createSwarmSlave(targetUrl);
swarmClient.createSwarmAgent(targetUrl);

/*
* Set up the label file watcher thread. If the label file changes, this thread
* takes action to restart the client. Note that this must be done after we create
* the swarm slave, since only then has the server returned the name we must use
* the Swarm agent, since only then has the server returned the name we must use
* when doing label operations.
*/
if (options.labelsFile != null) {
Expand Down
56 changes: 36 additions & 20 deletions client/src/main/java/hudson/plugins/swarm/Options.java
@@ -1,24 +1,29 @@
package hudson.plugins.swarm;

import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.MapOptionHandler;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.MapOptionHandler;

public class Options {

@Option(name = "-name", usage = "Name of the slave")
@Option(name = "-name", usage = "Name of the agent.")
public String name;

@Option(name = "-description", usage = "Description to be put on the slave")
@Option(name = "-description", usage = "Description to be put on the agent.")
public String description;

@Option(name = "-labels", usage = "Whitespace-separated list of labels to be assigned for this slave. Multiple options are allowed.")
@Option(
name = "-labels",
usage =
"Whitespace-separated list of labels to be assigned for this agent. Multiple"
+ " options are allowed.")
public List<String> labels = new ArrayList<>();

@Option(name = "-fsroot", usage = "Directory where Jenkins places files")
@Option(name = "-fsroot", usage = "Remote root directory.")
public File remoteFsRoot = new File(".");

@Option(name = "-executors", usage = "Number of executors")
Expand Down Expand Up @@ -55,7 +60,9 @@ public class Options {
@Option(name = "-maxRetryInterval", usage = "Max time to wait before retry in seconds. Default is 60 seconds.")
public int maxRetryInterval = 60;

@Option(name = "-disableSslVerification", usage = "Disables SSL verification in the HttpClient.")
@Option(
name = "-disableSslVerification",
usage = "Disable SSL verification in the HTTP client.")
public boolean disableSslVerification;

@Option(name = "-sslFingerprints", usage = "Whitespace-separated list of accepted certificate fingerprints (SHA-256/Hex), "+
Expand All @@ -64,34 +71,43 @@ public class Options {
"for custom fingerprints! Multiple options are allowed.")
public String sslFingerprints = "";

@Option(name = "-disableClientsUniqueId", usage = "Disables client's unique ID.")
@Option(name = "-disableClientsUniqueId", usage = "Disable client's unique ID.")
public boolean disableClientsUniqueId;

@Option(name = "-deleteExistingClients", usage = "Deletes any existing slave with the same name.")
@Option(
name = "-deleteExistingClients",
usage = "Delete any existing agent with the same name.")
public boolean deleteExistingClients;

@Option(
name = "-mode",
usage = "The mode controlling how Jenkins allocates jobs to slaves. Can be either '" + ModeOptionHandler.NORMAL + "' " +
"(utilize this slave as much as possible) or '" + ModeOptionHandler.EXCLUSIVE + "' (leave this machine for tied " +
"jobs only). Default is '" + ModeOptionHandler.NORMAL + "'.",
handler = ModeOptionHandler.class
)
usage =
"The mode controlling how Jenkins allocates jobs to agents. Can be either '"
+ ModeOptionHandler.NORMAL
+ "' (use this node as much as possible) or '"
+ ModeOptionHandler.EXCLUSIVE
+ "' (only build jobs with label expressions matching this node)."
+ " Default is '"
+ ModeOptionHandler.NORMAL
+ "'.",
handler = ModeOptionHandler.class)
public String mode = ModeOptionHandler.NORMAL;

@Option(
name = "-t", aliases = "--toolLocation",
usage = "A tool location to be defined on this slave. It is specified as 'toolName=location'",
handler = MapOptionHandler.class
)
name = "-t",
aliases = "--toolLocation",
usage =
"A tool location to be defined on this agent. It is specified as"
+ " 'toolName=location'.",
handler = MapOptionHandler.class)
public Map<String, String> toolLocations;

@Option(
name = "-e",
aliases = "--env",
usage =
"An environment variable to be defined on this slave. "
+ "It is specified as 'key=value'. Multiple variables are allowed.",
"An environment variable to be defined on this agent. It is specified as"
+ " 'key=value'. Multiple variables are allowed.",
handler = MapOptionHandler.class)
public Map<String, String> environmentVariables;

Expand Down
24 changes: 14 additions & 10 deletions client/src/main/java/hudson/plugins/swarm/SwarmClient.java
Expand Up @@ -55,7 +55,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.logging.Level;
Expand Down Expand Up @@ -129,7 +128,7 @@ public String discoverFromMasterUrl() throws IOException {
}

/**
* This method blocks while the swarm slave is serving as a slave.
* This method blocks while the Swarm agent is connected.
*
* <p>Interrupt the thread to abort it and return.
*/
Expand Down Expand Up @@ -305,8 +304,11 @@ private static synchronized Crumb getCsrfCrumb(
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
logger.log(
Level.SEVERE,
"Could not obtain CSRF crumb. Response code: "
+ response.getStatusLine().getStatusCode());
String.format(
"Could not obtain CSRF crumb. Response code: %s%n%s",
response.getStatusLine().getStatusCode(),
EntityUtils.toString(
response.getEntity(), StandardCharsets.UTF_8)));
return null;
}

Expand All @@ -325,8 +327,8 @@ private static synchronized Crumb getCsrfCrumb(
@SuppressFBWarnings(
value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
justification = "False positive for try-with-resources in Java 11")
protected void createSwarmSlave(String targetUrl) throws IOException, RetryException {
logger.fine("createSwarmSlave() invoked");
protected void createSwarmAgent(String targetUrl) throws IOException, RetryException {
logger.fine("createSwarmAgent() invoked");

CloseableHttpClient client = createHttpClient(options);
HttpClientContext context = createHttpClientContext(options, new URL(targetUrl));
Expand Down Expand Up @@ -392,7 +394,7 @@ protected void createSwarmSlave(String targetUrl) throws IOException, RetryExcep
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
String msg =
String.format(
"Failed to create a slave on Jenkins, response code: %s%n%s",
"Failed to create a Swarm agent on Jenkins. Response code: %s%n%s",
response.getStatusLine().getStatusCode(),
EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
logger.log(Level.SEVERE, msg);
Expand Down Expand Up @@ -462,7 +464,7 @@ protected static synchronized void postLabelRemove(
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
String msg =
String.format(
"Failed to remove slave labels. %s - %s",
"Failed to remove agent labels. Response code: %s%n%s",
response.getStatusLine().getStatusCode(),
EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
logger.log(Level.SEVERE, msg);
Expand Down Expand Up @@ -499,7 +501,7 @@ protected static synchronized void postLabelAppend(
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
String msg =
String.format(
"Failed to update slave labels. Slave is probably messed up. %s - %s",
"Failed to update agent labels. Response code: %s%n%s",
response.getStatusLine().getStatusCode(),
EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
logger.log(Level.SEVERE, msg);
Expand Down Expand Up @@ -558,7 +560,9 @@ static String getChildElementString(Element parent, String tagName) {
Element element = (Element) node;
if (element.getTagName().equals(tagName)) {
StringBuilder buf = new StringBuilder();
for (node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
for (node = element.getFirstChild();
node != null;
node = node.getNextSibling()) {
if (node instanceof Text) {
buf.append(node.getTextContent());
}
Expand Down
2 changes: 1 addition & 1 deletion plugin/pom.xml
Expand Up @@ -16,7 +16,7 @@

<artifactId>swarm</artifactId>
<packaging>hpi</packaging>
<name>Jenkins Self-Organizing Swarm Plug-in Modules</name>
<name>Swarm Plugin</name>
<url>https://github.com/jenkinsci/swarm-plugin</url>

<developers>
Expand Down