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-48050] Declarative Pipeline support for dockerNode #681

Merged
merged 22 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
edaef1e
Make it easier to run dockerNode by defaulting everything except the …
jglick Aug 22, 2018
2e32338
Oops, wrong Jenkins core version.
jglick Aug 22, 2018
bb990b6
Adding a pipeline-model-extensions dep.
jglick Aug 22, 2018
93f2fc2
Fixing Incrementals stuff.
jglick Aug 22, 2018
818b9a1
Merge branch 'incrementals' into declarative
jglick Aug 22, 2018
4dd11e7
[JENKINS-48050] Added dockerContainer agent type for Declarative.
jglick Aug 24, 2018
c770e0c
Reverting defaulting of remoteFs; the original default seems to work …
jglick Aug 24, 2018
92e62e0
Also ensure that Pipeline Syntax does not suggest remoteFs: ''.
jglick Aug 24, 2018
b342ce6
Merge branch 'defaults' into declarative
jglick Aug 24, 2018
963b4ea
Merge branch 'master' into declarative
jglick Aug 27, 2018
cb40068
Merge branch 'master' into declarative
jglick Sep 12, 2018
d3fab70
Merge branch 'master' into declarative
pjdarton Apr 2, 2020
fa248f3
Merge branch 'master' of github.com:jenkinsci/docker-plugin into decl…
jglick Apr 6, 2020
b6a93bf
RequireUpperBoundDeps
jglick Apr 6, 2020
579d140
Merge branch 'master' of https://github.com/jenkinsci/docker-plugin i…
jglick Dec 14, 2020
8451829
Merge branch 'master' of https://github.com/jenkinsci/docker-plugin i…
jglick May 23, 2023
dd2678d
Use a better-supported image https://github.com/jenkinsci/docker-plug…
jglick May 23, 2023
414e425
Add `serialVersionUID` to `DockerAgent` (though the impls in `pipelin…
jglick May 23, 2023
606d190
Merge branch 'master' of https://github.com/jenkinsci/docker-plugin i…
jglick May 23, 2023
13b6aae
Let `DockerAgent` use any args supported by `DockerNodeStep` https://…
jglick May 23, 2023
90617b2
Placating security scanner https://github.com/jenkinsci/docker-plugin…
jglick May 23, 2023
817669c
If `DockerNodeStep` is marked “⚠️ Experimental” then `DockerAgent` sh…
jglick May 23, 2023
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
2 changes: 1 addition & 1 deletion .mvn/extensions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<extension>
<groupId>io.jenkins.tools.incrementals</groupId>
<artifactId>git-changelist-maven-extension</artifactId>
<version>1.0-beta-3</version>
<version>1.0-beta-5</version>
</extension>
</extensions>
67 changes: 52 additions & 15 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>3.12</version>
<version>3.19</version>
<relativePath/>
</parent>

<groupId>io.jenkins.docker</groupId>
<artifactId>docker-plugin</artifactId>
<version>1.1.6-SNAPSHOT</version>
<version>${revision}${changelist}</version>
<packaging>hpi</packaging>

<name>Docker plugin</name>
Expand All @@ -25,12 +26,12 @@
</developers>

<properties>
<revision>1.1.5</revision>
<revision>1.1.6</revision>
<changelist>-SNAPSHOT</changelist>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.level>8</java.level>
<groovy.version>2.4.7</groovy.version>
<jenkins.version>2.60.3</jenkins.version>
<jenkins.version>2.73.3</jenkins.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -83,7 +84,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-api</artifactId>
<version>2.23.1</version>
<version>2.25</version>
<optional>true</optional>
</dependency>
<dependency>
Expand All @@ -95,34 +96,40 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>2.16</version>
<version>2.17</version>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.17</version>
<optional>true</optional>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.12.2</version>
<optional>true</optional>
<version>2.15</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>2.41</version>
<optional>true</optional>
<version>2.46</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.36</version>
<groupId>org.jenkinsci.plugins</groupId>
<artifactId>pipeline-model-extensions</artifactId>
<version>1.3.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkinsci.plugins</groupId>
<artifactId>pipeline-model-definition</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.kohlschutter.junixsocket</groupId>
Expand Down Expand Up @@ -185,10 +192,40 @@

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.42</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.9</version>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials</artifactId>
<version>2.1.16</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>ssh-credentials</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials-binding</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>scm-api</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-scm-step</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</dependencyManagement>
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/io/jenkins/docker/pipeline/DockerAgent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.jenkins.docker.pipeline;

import hudson.Extension;
import org.jenkinsci.Symbol;
import org.jenkinsci.plugins.pipeline.modeldefinition.agent.DeclarativeAgent;
import org.jenkinsci.plugins.pipeline.modeldefinition.agent.DeclarativeAgentDescriptor;
import org.kohsuke.stapler.DataBoundConstructor;

@SuppressWarnings("unchecked") // TODO DeclarativeAgent.getDescriptor problem
public class DockerAgent extends DeclarativeAgent<DockerAgent> {
jglick marked this conversation as resolved.
Show resolved Hide resolved

public final String image;

@DataBoundConstructor
public DockerAgent(String image) {
this.image = image;
}

// TODO other properties accepted by DockerNodeStep
jglick marked this conversation as resolved.
Show resolved Hide resolved

@Symbol("dockerContainer")
@Extension
public static class DescriptorImpl extends DeclarativeAgentDescriptor<DockerAgent> {

@Override
public String getDisplayName() {
return "Start a Docker container with a new agent";
}

}

}
13 changes: 9 additions & 4 deletions src/main/java/io/jenkins/docker/pipeline/DockerNodeStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Item;
import hudson.model.Node;
Expand Down Expand Up @@ -36,27 +37,31 @@ public class DockerNodeStep extends Step {

private String image;

private String remoteFs;
private String remoteFs = "/tmp";

private DockerComputerConnector connector;

@DataBoundConstructor
public DockerNodeStep(String dockerHost, String image) {
this.dockerHost = dockerHost;
public DockerNodeStep(String image) {
this.image = image;
}

public String getDockerHost() {
return dockerHost;
}

@DataBoundSetter
public void setDockerHost(String dockerHost) {
this.dockerHost = Util.fixEmpty(dockerHost);
}

public String getCredentialsId() {
return credentialsId;
}

@DataBoundSetter
public void setCredentialsId(String credentialsId) {
this.credentialsId = credentialsId;
this.credentialsId = Util.fixEmpty(credentialsId);
}

public String getImage() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package io.jenkins.docker.pipeline;

import com.nirima.jenkins.plugins.docker.DockerCloud;
import com.nirima.jenkins.plugins.docker.DockerTemplate;
import com.nirima.jenkins.plugins.docker.DockerTemplateBase;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Util;
import hudson.console.PlainTextConsoleOutputStream;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.model.TaskListener;
import hudson.slaves.Cloud;
import io.jenkins.docker.DockerTransientNode;
import io.jenkins.docker.client.DockerAPI;
import io.jenkins.docker.connector.DockerComputerAttachConnector;
import io.jenkins.docker.connector.DockerComputerConnector;
import jenkins.model.Jenkins;
import jenkins.model.NodeListener;
import org.jenkinsci.plugins.docker.commons.credentials.DockerServerEndpoint;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback;
Expand All @@ -23,11 +23,9 @@
import org.jenkinsci.plugins.workflow.support.actions.WorkspaceActionImpl;

import javax.annotation.Nonnull;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
Expand Down Expand Up @@ -77,13 +75,18 @@ private DockerTransientNode createNode(TaskListener listener) {
final String uuid = UUID.randomUUID().toString();

final DockerTemplate t = new DockerTemplate(
new DockerTemplateBase(image),
new DockerTemplateBase(image), // TODO call .setPullCredentialsId and also add option to .setRegistryUrl or similar
connector,
uuid, remoteFs, "1");

t.setMode(Node.Mode.EXCLUSIVE);

final DockerAPI api = new DockerAPI(new DockerServerEndpoint(dockerHost, credentialsId));
final DockerAPI api;
if (dockerHost == null && credentialsId == null) {
api = defaultApi();
} else {
api = new DockerAPI(new DockerServerEndpoint(dockerHost, credentialsId));
}

DockerTransientNode node;
Computer computer = null;
Expand Down Expand Up @@ -114,6 +117,15 @@ private DockerTransientNode createNode(TaskListener listener) {
return node;
}

private static DockerAPI defaultApi() {
for (Cloud cloud : Jenkins.getInstance().clouds) {
if (cloud instanceof DockerCloud) {
return ((DockerCloud) cloud).getDockerApi();
}
}
throw new IllegalStateException("Must either specify dockerHost/credentialsId, or define at least one Docker cloud");
}


private void invokeBody(DockerTransientNode node, TaskListener listener) {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry field="image" title="Image">
<f:textbox/>
</f:entry>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.jenkins.docker.pipeline

import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
import org.jenkinsci.plugins.pipeline.modeldefinition.agent.CheckoutScript
import org.jenkinsci.plugins.pipeline.modeldefinition.agent.DeclarativeAgentScript
import org.jenkinsci.plugins.workflow.cps.CpsScript

class DockerAgentScript extends DeclarativeAgentScript<DockerAgent> {

DockerAgentScript(CpsScript s, DockerAgent a) {
super(s, a)
}

@Override
Closure run(Closure body) {
return {
try {
script.dockerNode(describable?.image) {
CheckoutScript.doCheckout(script, describable, null, body).call()
}
} catch (Exception e) {
script.getProperty("currentBuild").result = Utils.getResultFromException(e)
throw e
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:c="/lib/credentials">

<f:entry title="Docker Host" field="dockerHost">
<f:textbox/>
</f:entry>

<f:entry field="credentialsId" title="Docker API credentials">
<c:select/>
</f:entry>

<f:entry title="Docker image" field="image">
<f:textbox/>
</f:entry>

<f:entry title="Agent root directory" field="remoteFs">
<f:textbox/>
<f:textbox default="/tmp"/>
</f:entry>

<f:advanced>

<f:entry title="Docker Host" field="dockerHost">
<f:textbox/>
</f:entry>

<f:entry field="credentialsId" title="Docker API credentials">
<c:select/>
</f:entry>

</f:advanced>

</j:jelly>
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
<p>
Allocates a new Jenkins agent using a specified Docker image and runs tasks on it. Example:
</p>
<pre>docker-node(image: 'cloudbees/jnlp-slave-with-java-build-tools') {
<pre>dockerNode('cloudbees/jnlp-slave-with-java-build-tools') {
git 'https://github.com/jglick/simple-maven-project-with-tests'
withMaven {
sh 'mvn install'
}
sh 'mvn -B -Dmaven.test.failure.ignore install'
junit '**/target/surefire-reports/TEST-*.xml'
}</pre>
</div>
Loading