diff --git a/pom.xml b/pom.xml
index 3e1a70926..d021bab11 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,7 @@
8
2.9
2.12
+ 2.25
@@ -57,7 +58,7 @@
org.jenkins-ci.plugins.workflow
workflow-cps
- 2.25
+ ${workflow-cps-plugin.version}
org.jenkins-ci.plugins.workflow
@@ -103,6 +104,13 @@
tests
test
+
+ org.jenkins-ci.plugins.workflow
+ workflow-cps
+ ${workflow-cps-plugin.version}
+ tests
+ test
+
org.jenkins-ci.plugins.workflow
workflow-job
diff --git a/src/main/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStep.java b/src/main/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStep.java
index d74ecfdd7..47ced2eb5 100644
--- a/src/main/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStep.java
+++ b/src/main/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStep.java
@@ -28,17 +28,24 @@
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
+import hudson.Util;
import hudson.model.Job;
import hudson.model.Node;
import hudson.model.TaskListener;
import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.jenkinsci.plugins.docker.commons.credentials.DockerRegistryEndpoint;
import org.jenkinsci.plugins.docker.commons.credentials.KeyMaterialFactory;
import org.jenkinsci.plugins.docker.commons.tools.DockerTool;
+import org.jenkinsci.plugins.structs.describable.UninstantiatedDescribable;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
+import org.jenkinsci.plugins.workflow.steps.Step;
import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
@@ -62,7 +69,7 @@ public String getToolName() {
}
@DataBoundSetter public void setToolName(String toolName) {
- this.toolName = toolName;
+ this.toolName = Util.fixEmpty(toolName);
}
public static class Execution extends AbstractEndpointStepExecution {
@@ -105,6 +112,29 @@ public DescriptorImpl() {
return true;
}
+ @Override public UninstantiatedDescribable uninstantiate(Step step) throws UnsupportedOperationException {
+ RegistryEndpointStep s = (RegistryEndpointStep) step;
+ Map args = new TreeMap<>();
+ args.put("url", s.registry.getUrl());
+ args.put("credentialsId", s.registry.getCredentialsId());
+ args.put("toolName", s.toolName);
+ args.values().removeAll(Collections.singleton(null));
+ return new UninstantiatedDescribable(args);
+ }
+
+ @Override public Step newInstance(Map arguments) throws Exception {
+ arguments = new HashMap<>(arguments);
+ if (arguments.containsKey("url") || arguments.containsKey("credentialsId")) {
+ if (arguments.containsKey("registry")) {
+ throw new IllegalArgumentException("cannot mix url/credentialsId with registry");
+ }
+ arguments.put("registry", new DockerRegistryEndpoint((String) arguments.remove("url"), (String) arguments.remove("credentialsId")));
+ } else if (!arguments.containsKey("registry")) {
+ throw new IllegalArgumentException("must specify url/credentialsId (or registry)");
+ }
+ return super.newInstance(arguments);
+ }
+
}
}
diff --git a/src/main/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStep.java b/src/main/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStep.java
index 4bbe854bb..8ddf52e15 100644
--- a/src/main/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStep.java
+++ b/src/main/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStep.java
@@ -85,6 +85,8 @@ public DescriptorImpl() {
return true;
}
+ // TODO allow DockerServerEndpoint fields to be inlined, as in RegistryEndpointStep, so Docker.groovy can say simply: script.withDockerServer(uri: uri, credentialsId: credentialsId) {…}
+
}
}
diff --git a/src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy b/src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy
index 45159f9f1..97dad6030 100644
--- a/src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy
+++ b/src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy
@@ -37,7 +37,7 @@ class Docker implements Serializable {
public V withRegistry(String url, String credentialsId = null, Closure body) {
node {
script.withEnv(["DOCKER_REGISTRY_URL=${url}"]) {
- script.withDockerRegistry(registry: [url: url, credentialsId: credentialsId], toolName: script.env.DOCKER_TOOL_NAME) {
+ script.withDockerRegistry(url: url, credentialsId: credentialsId, toolName: script.env.DOCKER_TOOL_NAME) {
body()
}
}
diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java
index eda6e270f..1e5590444 100644
--- a/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java
+++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java
@@ -28,45 +28,59 @@
import com.cloudbees.plugins.credentials.common.IdCredentials;
import com.cloudbees.plugins.credentials.domains.Domain;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
import org.jenkinsci.plugins.docker.commons.credentials.DockerRegistryEndpoint;
+import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
+import org.jenkinsci.plugins.workflow.cps.SnippetizerTester;
+import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.steps.StepConfigTester;
-import org.jenkinsci.plugins.workflow.structs.DescribableHelper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.runners.model.Statement;
-import org.jvnet.hudson.test.BuildWatcher;
-import org.jvnet.hudson.test.RestartableJenkinsRule;
+import org.jvnet.hudson.test.Issue;
+import org.jvnet.hudson.test.JenkinsRule;
public class RegistryEndpointStepTest {
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public RestartableJenkinsRule story = new RestartableJenkinsRule();
+ @Rule public JenkinsRule r = new JenkinsRule();
- @Test public void configRoundTrip() {
- story.addStep(new Statement() {
- @Override public void evaluate() throws Throwable {
- IdCredentials registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "pass");
- CredentialsProvider.lookupStores(story.j.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials);
- StepConfigTester sct = new StepConfigTester(story.j);
- Map registryConfig = new TreeMap();
- registryConfig.put("url", "https://docker.my.com/");
- registryConfig.put("credentialsId", registryCredentials.getId());
- Map config = Collections.singletonMap("registry", registryConfig);
- RegistryEndpointStep step = DescribableHelper.instantiate(RegistryEndpointStep.class, config);
- step = sct.configRoundTrip(step);
- DockerRegistryEndpoint registry = step.getRegistry();
- assertNotNull(registry);
- assertEquals("https://docker.my.com/", registry.getUrl());
- assertEquals(registryCredentials.getId(), registry.getCredentialsId());
- assertEquals(config, DescribableHelper.uninstantiate(step));
- }
- });
+ @Issue("JENKINS-51395")
+ @Test public void configRoundTrip() throws Exception {
+ { // Recommended syntax.
+ SnippetizerTester st = new SnippetizerTester(r);
+ RegistryEndpointStep step = new RegistryEndpointStep(new DockerRegistryEndpoint("https://myreg/", null));
+ step.setToolName("");
+ st.assertRoundTrip(step, "withDockerRegistry(url: 'https://myreg/') {\n // some block\n}");
+ step = new RegistryEndpointStep(new DockerRegistryEndpoint(null, "hubcreds"));
+ st.assertRoundTrip(step, "withDockerRegistry(credentialsId: 'hubcreds') {\n // some block\n}");
+ step = new RegistryEndpointStep(new DockerRegistryEndpoint("https://myreg/", "mycreds"));
+ step.setToolName("ce");
+ st.assertRoundTrip(step, "withDockerRegistry(credentialsId: 'mycreds', toolName: 'ce', url: 'https://myreg/') {\n // some block\n}");
+ }
+ { // Older syntax.
+ WorkflowJob p = r.createProject(WorkflowJob.class, "p");
+ p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry(registry: [url: 'https://docker.my.com/'], toolName: 'irrelevant') {}}", true));
+ r.buildAndAssertSuccess(p);
+ p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry(registry: [url: 'https://docker.my.com/']) {}}", true));
+ r.buildAndAssertSuccess(p);
+ p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry([url: 'https://docker.my.com/']) {}}", true));
+ r.buildAndAssertSuccess(p);
+ // and new, just in case SnippetizerTester is faking it:
+ p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry(url: 'https://docker.my.com/') {}}", true));
+ r.buildAndAssertSuccess(p);
+ }
+ { // UI form.
+ IdCredentials registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "pass");
+ CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials);
+ StepConfigTester sct = new StepConfigTester(r);
+ RegistryEndpointStep step = new RegistryEndpointStep(new DockerRegistryEndpoint("https://docker.my.com/", "registryCreds"));
+ step = sct.configRoundTrip(step);
+ DockerRegistryEndpoint registry = step.getRegistry();
+ assertNotNull(registry);
+ assertEquals("https://docker.my.com/", registry.getUrl());
+ assertEquals("registryCreds", registry.getCredentialsId());
+ // TODO check toolName
+ }
}
}
\ No newline at end of file