Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ Next you need to add one or more agent templates. Make sure to set a `label`. A
The plugin attempts to create an agent as soon as build enters the queue. Bypassing cloud apis for faster agent scheduling.

## Caching
Caching is done via [docker volume plugin](https://github.com/suryagaddipati/docker-cache-volume-plugin).
There are 2 options:
1. **Caching is done via [docker volume plugin](https://github.com/suryagaddipati/docker-cache-volume-plugin).**
Driver gets called to create an overlayfs cache volume for each build and once build is done volume gets deleted. This cache volume is mounted into agent in the directory specified by `Cache Dir` configuration option in Agent Templates. On delete if there are any new changes to cache they get copied into a new basedir and pointer to baseCache gets updated. You can optionally mount lower base cache dir onto a NFS storage appliance. Checkout plugin documentation for more details.
1. **Caching is done via the default docker volume driver.** To activate it, type `local` into the `Cache driver name` field in the docker swarm cloud configuration.
Watch out for concurrent access as it is possible for 2 containers to access the same cache at the same time. This is not an issue if you use it as a repository cache when controlled by git or mercurial. They have internal mechanisms for serializing access.

## Swarm Dashboard
Follow the link `Docker Swarm Dashboard` on the sidebar to view the status of your swarm. It displays what build is executing where, what builds are in the queue for what resources ect.
Expand Down
70 changes: 19 additions & 51 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.0</version>
<version>4.88</version>
<relativePath />
</parent>
<groupId>org.jenkins-ci.plugins</groupId>
Expand All @@ -22,17 +22,29 @@
</license>
</licenses>
<scm>
<connection>scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git</connection>
<connection>scm:git:https://github.com/jenkinsci/${project.artifactId}-plugin.git</connection>
<developerConnection>scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git</developerConnection>
<url>https://github.com/jenkinsci/${project.artifactId}-plugin</url>
<tag>HEAD</tag>
</scm>
<properties>
<jenkins.version>2.222.4</jenkins.version>
<java.level>8</java.level>
<jackson-jaxrs.version>2.6.4</jackson-jaxrs.version>
<!-- https://www.jenkins.io/doc/developer/plugin-development/choosing-jenkins-baseline/ -->
<jenkins.baseline>2.462</jenkins.baseline>
<jenkins.version>${jenkins.baseline}.3</jenkins.version>
<hpi.bundledArtifacts>akka-actor_2.12,config,okhttp,okio,scala-java8-compat_2.12,scala-library</hpi.bundledArtifacts>
<spotbugs.skip>true</spotbugs.skip>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-${jenkins.baseline}.x</artifactId>
<version>4228.v0a_71308d905b_</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
Expand All @@ -45,76 +57,32 @@
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>docker-commons</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>docker-java-api</artifactId>
<version>3.0.14</version>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.9.9</version>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>jackson2-api</artifactId>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_2.12</artifactId>
<version>2.5.25</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson-jaxrs.version}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>durable-task</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency>
</dependencies>
<developers>
<developer>
<id>surya548</id>
<name>Surya Gaddipati</name>
</developer>
<developer>
<id>roemer</id>
<name>Roman Bäriswyl</name>
</developer>
</developers>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Nonnull;

import org.jenkinsci.plugins.durabletask.executors.ContinuableExecutable;
import org.kohsuke.stapler.DataBoundConstructor;

Expand Down Expand Up @@ -41,7 +39,7 @@ public long getTimeout() {
}

@Override
public long check(@Nonnull DockerSwarmComputer c) {
public long check(DockerSwarmComputer c) {
if (c.isIdle() && c.isOnline()) {
final long connectTime = System.currentTimeMillis() - c.getConnectTime();
final long onlineTime = System.currentTimeMillis() - c.getOnlineTime();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class DockerSwarmAgentTemplate implements Describable<DockerSwarmAgentTem
private String hosts;

private String cacheDir;
private String volumeDir;
private String envVars;
private String baseWorkspaceLocation;
private String placementConstraints;
Expand All @@ -60,7 +61,7 @@ public DockerSwarmAgentTemplate() {
public DockerSwarmAgentTemplate(final String image, final String hostBinds, final String hostNamedPipes, final String dnsIps,
final String dnsSearchDomains, final String unixCommand,final String windowsCommand, final String user, final String workingDir,
final String hosts, final String metadata, final String secrets, final String configs, final String label, final String cacheDir,
final String tmpfsDir, final String envVars, final long limitsNanoCPUs, final long limitsMemoryBytes,
final String volumeDir, final String tmpfsDir, final String envVars, final long limitsNanoCPUs, final long limitsMemoryBytes,
final long reservationsNanoCPUs, final long reservationsMemoryBytes, String portBinds, final boolean osWindows,
final String baseWorkspaceLocation, final String placementConstraints, final String placementArchitecture,
final String placementOperatingSystem, final String email, final String serverAddress, final String pullCredentialsId) {
Expand All @@ -79,6 +80,7 @@ public DockerSwarmAgentTemplate(final String image, final String hostBinds, fina
this.configs = configs;
this.label = label;
this.cacheDir = cacheDir;
this.volumeDir = volumeDir;
this.tmpfsDir = tmpfsDir;
this.limitsNanoCPUs = limitsNanoCPUs;
this.limitsMemoryBytes = limitsMemoryBytes;
Expand All @@ -100,6 +102,10 @@ public String[] getCacheDirs() {
return StringUtils.isEmpty(this.cacheDir) ? new String[] {} : this.cacheDir.split("[\\r\\n ]+");
}

public String[] getVolumeDirs() {
return StringUtils.isEmpty(this.volumeDir) ? new String[] {} : this.volumeDir.split("[\\r\\n ]+");
}

public String getLabel() {
return this.label;
}
Expand Down Expand Up @@ -148,8 +154,17 @@ public String[] getEnvVarsConfig() {
return StringUtils.isEmpty(this.envVars) ? new String[] {} : this.envVars.split("[\\r\\n]+");
}

private static final String[] DEFAULT_UNIX_COMMAND = {
"sh", "-cx",
"curl --connect-timeout 20 --max-time 60 -o agent.jar $DOCKER_SWARM_PLUGIN_JENKINS_AGENT_JAR_URL"
+ " && java -classpath agent.jar hudson.remoting.jnlp.Main -headless"
+ " -url $DOCKER_SWARM_PLUGIN_JENKINS_URL"
+ " -workDir /tmp"
+ " $DOCKER_SWARM_PLUGIN_JENKINS_AGENT_SECRET $DOCKER_SWARM_PLUGIN_JENKINS_AGENT_NAME"
};

public String[] getUnixCommandConfig() {
return StringUtils.isEmpty(this.unixCommand) ? new String[] {} : this.unixCommand.split("[\\r\\n]+");
return StringUtils.isEmpty(this.unixCommand) ? DEFAULT_UNIX_COMMAND : this.unixCommand.split("[\\r\\n]+");
}
public String[] getWindowsCommandConfig() {
return StringUtils.isEmpty(this.windowsCommand) ? new String[] {} : this.windowsCommand.split("[\\r\\n\\s]+");
Expand Down Expand Up @@ -286,6 +301,10 @@ public String getCacheDir() {
return cacheDir;
}

public String getVolumeDir() {
return volumeDir;
}

public String getUser() {
return user;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public void launchContainer(String[] commands, DockerSwarmCloud configuration, S
setConfigs(dockerSwarmAgentTemplate, crReq);
setNetwork(configuration, crReq);
setCacheDirs(configuration, dockerSwarmAgentTemplate, listener, computer, crReq);
setVolumeDirs(configuration, dockerSwarmAgentTemplate, listener, computer, crReq);
setTmpfs(dockerSwarmAgentTemplate, crReq);
setPlacement(dockerSwarmAgentTemplate, crReq);
setLabels(crReq);
Expand Down Expand Up @@ -202,12 +203,25 @@ private void setCacheDirs(DockerSwarmCloud configuration, DockerSwarmAgentTempla
final String cacheVolumeName = getJobName() + "-" + computer.getVolumeName();
this.bi.getAction(DockerSwarmAgentInfo.class).setCacheVolumeName(cacheVolumeName);
for (int i = 0; i < cacheDirs.length; i++) {
listener.getLogger().println("Binding Volume" + cacheDirs[i] + " to " + cacheVolumeName);
listener.getLogger().println("Binding Volume " + cacheVolumeName + " to " + cacheDirs[i]);
crReq.addCacheVolume(cacheVolumeName, cacheDirs[i], configuration.getCacheDriverName());
}
}
}

private void setVolumeDirs(DockerSwarmCloud configuration, DockerSwarmAgentTemplate dockerSwarmAgentTemplate,
TaskListener listener, DockerSwarmComputer computer, ServiceSpec crReq) {
final String[] volumeDirs = dockerSwarmAgentTemplate.getVolumeDirs();
if (volumeDirs.length > 0) {
for (int i = 0; i < volumeDirs.length; i++) {
final String cacheVolumeName = volumeDirs[i].split(":")[0];
final String mountDir = volumeDirs[i].split(":")[1];
listener.getLogger().println("Binding Volume " + cacheVolumeName + " to " + mountDir);
crReq.addCacheVolume(cacheVolumeName, mountDir, configuration.getCacheDriverName());
}
}
}

private void setNetwork(DockerSwarmCloud configuration, ServiceSpec crReq) {
crReq.setNetwork(configuration.getSwarmNetwork());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public String getCpuUsage() throws IOException {

final JSONArray mJSONArray = new JSONArray();
mJSONArray.addAll(usage);
return mJSONArray.toString();
return mJSONArray.toString().replace("</", "<\\/");
}

public String getMemoryUsage() throws IOException {
Expand Down Expand Up @@ -124,7 +124,7 @@ public String getMemoryUsage() throws IOException {

final JSONArray mJSONArray = new JSONArray();
mJSONArray.addAll(usage);
return mJSONArray.toString();
return mJSONArray.toString().replace("</", "<\\/");
}

private List<SwarmNode> calculateNodes() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ public String getRole() {
return this.role;
}

public String getSafeId() {
if (this.name == null) {
return "_unknown_";
}
return this.name.replaceAll("[^a-zA-Z0-9-]", "_");
}

public boolean isHealthy() {
return this.healthy == "ready";
}
Expand Down Expand Up @@ -121,7 +128,7 @@ public String getCpuUsageJson() {
usage.add(Arrays.asList("reserved", getReservedCPUs()));
final JSONArray mJSONArray = new JSONArray();
mJSONArray.addAll(usage);
return mJSONArray.toString();
return mJSONArray.toString().replace("</", "<\\/");
}

public String getMemoryUsageJson() {
Expand All @@ -131,6 +138,6 @@ public String getMemoryUsageJson() {
usage.add(Arrays.asList("reserved", getReservedMemory()));
final JSONArray mJSONArray = new JSONArray();
mJSONArray.addAll(usage);
return mJSONArray.toString();
return mJSONArray.toString().replace("</", "<\\/");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonInclude;

public class ContainerSpec {

public final String Image;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public final String[] Command;
public final String[] Env;
public final String Dir;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
package org.jenkinsci.plugins.docker.swarm.docker.api.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
Expand All @@ -26,8 +24,6 @@ public class ServiceSpec extends ApiRequest {
public String Name;
public Map<String, String> Labels = new HashMap<>();

public List<Network> Networks = new ArrayList<>();

public ServiceSpec(String name, String Image, String[] Cmd, String[] Env, String Dir, String User, String[] Hosts)
throws IOException {
super(HttpMethod.POST, "/services/create", CreateServiceResponse.class, ResponseType.CLASS);
Expand Down Expand Up @@ -92,9 +88,10 @@ public void setTaskReservations(long nanoCPUs, long memoryBytes) {
this.TaskTemplate.Resources.Reservations.MemoryBytes = memoryBytes;
}

// ServceSpec.Networks deprecated since Docker API v1.44, use TaskTemplate.Networks instead
public void setNetwork(String network) {
if (!Strings.isNullOrEmpty(network)) {
Networks.add(new Network(network));
this.TaskTemplate.Networks.add(new Network(network));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package org.jenkinsci.plugins.docker.swarm.docker.api.task;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jenkinsci.plugins.docker.swarm.docker.api.containers.ContainerSpec;
import org.jenkinsci.plugins.docker.swarm.docker.api.network.Network;

public class TaskTemplate {
public org.jenkinsci.plugins.docker.swarm.docker.api.containers.ContainerSpec ContainerSpec;
public RestartPolicy RestartPolicy = new RestartPolicy();
public Resources Resources = new Resources();
public Placement Placement;
public List<Network> Networks = new ArrayList<>();

public TaskTemplate() {
// for reading from api
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
<f:entry title="Cache Dirs (newline-separated)" field="cacheDir">
<f:expandableTextbox value="${dockerSwarmAgentTemplate.cacheDir}"/>
</f:entry>
<f:entry title="Docker volumes (newline-separated)" field="volumeDir">
<f:expandableTextbox value="${dockerSwarmAgentTemplate.volumeDir}"/>
</f:entry>

<f:entry title="Tmpfs Dir" field="tmpfsDir">
<f:textbox value="${dockerSwarmAgentTemplate.tmpfsDir}"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div>
<p>Option to enable a volume and mount to the specified folder. The Volume name will be uniquely generated per node and per job. This makes it possible to have a cache for a job which is node persistent. For the behavior in case of concurrent access, see documanetation of the docker storage driver you are using.</p>
<code>
/FolderToMountVolume
</code>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div>
<p>
Option to enable a custom volume and mount to the specified folder. Similar to 'Cache dirs', except that you can choose here the volume name. Hence it will not be unique per job.
This is interesting if you want to reuse information between multiple jobs or just to save disk space. One of the use cases can be as a repository cache.
</p>
<code>
volumeName:/FolderToMountVolume
</code>
</div>
Loading