Skip to content

Commit e8a1815

Browse files
authored
Merge pull request #138 from jglick/withDockerRegistry-syntax-JENKINS-51395
[JENKINS-51395] Syntax problems in withDockerRegistry
2 parents c5a7394 + a03096b commit e8a1815

5 files changed

Lines changed: 86 additions & 32 deletions

File tree

pom.xml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<java.level>8</java.level>
3636
<workflow-step-api-plugin.version>2.9</workflow-step-api-plugin.version>
3737
<workflow-support-plugin.version>2.12</workflow-support-plugin.version>
38+
<workflow-cps-plugin.version>2.25</workflow-cps-plugin.version>
3839
</properties>
3940
<repositories>
4041
<repository>
@@ -57,7 +58,7 @@
5758
<dependency>
5859
<groupId>org.jenkins-ci.plugins.workflow</groupId>
5960
<artifactId>workflow-cps</artifactId>
60-
<version>2.25</version>
61+
<version>${workflow-cps-plugin.version}</version>
6162
</dependency>
6263
<dependency>
6364
<groupId>org.jenkins-ci.plugins.workflow</groupId>
@@ -103,6 +104,13 @@
103104
<classifier>tests</classifier>
104105
<scope>test</scope>
105106
</dependency>
107+
<dependency>
108+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
109+
<artifactId>workflow-cps</artifactId>
110+
<version>${workflow-cps-plugin.version}</version>
111+
<classifier>tests</classifier>
112+
<scope>test</scope>
113+
</dependency>
106114
<dependency>
107115
<groupId>org.jenkins-ci.plugins.workflow</groupId>
108116
<artifactId>workflow-job</artifactId>

src/main/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStep.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,24 @@
2828
import hudson.Extension;
2929
import hudson.FilePath;
3030
import hudson.Launcher;
31+
import hudson.Util;
3132
import hudson.model.Job;
3233
import hudson.model.Node;
3334
import hudson.model.TaskListener;
3435
import java.io.IOException;
36+
import java.util.Collections;
37+
import java.util.HashMap;
38+
import java.util.Map;
39+
import java.util.TreeMap;
3540
import javax.annotation.CheckForNull;
3641
import javax.annotation.Nonnull;
3742
import org.jenkinsci.plugins.docker.commons.credentials.DockerRegistryEndpoint;
3843
import org.jenkinsci.plugins.docker.commons.credentials.KeyMaterialFactory;
3944
import org.jenkinsci.plugins.docker.commons.tools.DockerTool;
45+
import org.jenkinsci.plugins.structs.describable.UninstantiatedDescribable;
4046
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
4147
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
48+
import org.jenkinsci.plugins.workflow.steps.Step;
4249
import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
4350
import org.kohsuke.stapler.DataBoundConstructor;
4451
import org.kohsuke.stapler.DataBoundSetter;
@@ -62,7 +69,7 @@ public String getToolName() {
6269
}
6370

6471
@DataBoundSetter public void setToolName(String toolName) {
65-
this.toolName = toolName;
72+
this.toolName = Util.fixEmpty(toolName);
6673
}
6774

6875
public static class Execution extends AbstractEndpointStepExecution {
@@ -105,6 +112,29 @@ public DescriptorImpl() {
105112
return true;
106113
}
107114

115+
@Override public UninstantiatedDescribable uninstantiate(Step step) throws UnsupportedOperationException {
116+
RegistryEndpointStep s = (RegistryEndpointStep) step;
117+
Map<String, Object> args = new TreeMap<>();
118+
args.put("url", s.registry.getUrl());
119+
args.put("credentialsId", s.registry.getCredentialsId());
120+
args.put("toolName", s.toolName);
121+
args.values().removeAll(Collections.singleton(null));
122+
return new UninstantiatedDescribable(args);
123+
}
124+
125+
@Override public Step newInstance(Map<String, Object> arguments) throws Exception {
126+
arguments = new HashMap<>(arguments);
127+
if (arguments.containsKey("url") || arguments.containsKey("credentialsId")) {
128+
if (arguments.containsKey("registry")) {
129+
throw new IllegalArgumentException("cannot mix url/credentialsId with registry");
130+
}
131+
arguments.put("registry", new DockerRegistryEndpoint((String) arguments.remove("url"), (String) arguments.remove("credentialsId")));
132+
} else if (!arguments.containsKey("registry")) {
133+
throw new IllegalArgumentException("must specify url/credentialsId (or registry)");
134+
}
135+
return super.newInstance(arguments);
136+
}
137+
108138
}
109139

110140
}

src/main/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStep.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ public DescriptorImpl() {
8585
return true;
8686
}
8787

88+
// TODO allow DockerServerEndpoint fields to be inlined, as in RegistryEndpointStep, so Docker.groovy can say simply: script.withDockerServer(uri: uri, credentialsId: credentialsId) {…}
89+
8890
}
8991

9092
}

src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Docker implements Serializable {
3737
public <V> V withRegistry(String url, String credentialsId = null, Closure<V> body) {
3838
node {
3939
script.withEnv(["DOCKER_REGISTRY_URL=${url}"]) {
40-
script.withDockerRegistry(registry: [url: url, credentialsId: credentialsId], toolName: script.env.DOCKER_TOOL_NAME) {
40+
script.withDockerRegistry(url: url, credentialsId: credentialsId, toolName: script.env.DOCKER_TOOL_NAME) {
4141
body()
4242
}
4343
}

src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,45 +28,59 @@
2828
import com.cloudbees.plugins.credentials.common.IdCredentials;
2929
import com.cloudbees.plugins.credentials.domains.Domain;
3030
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
31-
import java.util.Collections;
32-
import java.util.Map;
33-
import java.util.TreeMap;
3431
import org.jenkinsci.plugins.docker.commons.credentials.DockerRegistryEndpoint;
32+
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
33+
import org.jenkinsci.plugins.workflow.cps.SnippetizerTester;
34+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
3535
import org.jenkinsci.plugins.workflow.steps.StepConfigTester;
36-
import org.jenkinsci.plugins.workflow.structs.DescribableHelper;
3736
import static org.junit.Assert.assertEquals;
3837
import static org.junit.Assert.assertNotNull;
39-
import org.junit.ClassRule;
4038
import org.junit.Rule;
4139
import org.junit.Test;
42-
import org.junit.runners.model.Statement;
43-
import org.jvnet.hudson.test.BuildWatcher;
44-
import org.jvnet.hudson.test.RestartableJenkinsRule;
40+
import org.jvnet.hudson.test.Issue;
41+
import org.jvnet.hudson.test.JenkinsRule;
4542

4643
public class RegistryEndpointStepTest {
4744

48-
@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
49-
@Rule public RestartableJenkinsRule story = new RestartableJenkinsRule();
45+
@Rule public JenkinsRule r = new JenkinsRule();
5046

51-
@Test public void configRoundTrip() {
52-
story.addStep(new Statement() {
53-
@Override public void evaluate() throws Throwable {
54-
IdCredentials registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "pass");
55-
CredentialsProvider.lookupStores(story.j.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials);
56-
StepConfigTester sct = new StepConfigTester(story.j);
57-
Map<String,Object> registryConfig = new TreeMap<String,Object>();
58-
registryConfig.put("url", "https://docker.my.com/");
59-
registryConfig.put("credentialsId", registryCredentials.getId());
60-
Map<String,Object> config = Collections.<String,Object>singletonMap("registry", registryConfig);
61-
RegistryEndpointStep step = DescribableHelper.instantiate(RegistryEndpointStep.class, config);
62-
step = sct.configRoundTrip(step);
63-
DockerRegistryEndpoint registry = step.getRegistry();
64-
assertNotNull(registry);
65-
assertEquals("https://docker.my.com/", registry.getUrl());
66-
assertEquals(registryCredentials.getId(), registry.getCredentialsId());
67-
assertEquals(config, DescribableHelper.uninstantiate(step));
68-
}
69-
});
47+
@Issue("JENKINS-51395")
48+
@Test public void configRoundTrip() throws Exception {
49+
{ // Recommended syntax.
50+
SnippetizerTester st = new SnippetizerTester(r);
51+
RegistryEndpointStep step = new RegistryEndpointStep(new DockerRegistryEndpoint("https://myreg/", null));
52+
step.setToolName("");
53+
st.assertRoundTrip(step, "withDockerRegistry(url: 'https://myreg/') {\n // some block\n}");
54+
step = new RegistryEndpointStep(new DockerRegistryEndpoint(null, "hubcreds"));
55+
st.assertRoundTrip(step, "withDockerRegistry(credentialsId: 'hubcreds') {\n // some block\n}");
56+
step = new RegistryEndpointStep(new DockerRegistryEndpoint("https://myreg/", "mycreds"));
57+
step.setToolName("ce");
58+
st.assertRoundTrip(step, "withDockerRegistry(credentialsId: 'mycreds', toolName: 'ce', url: 'https://myreg/') {\n // some block\n}");
59+
}
60+
{ // Older syntax.
61+
WorkflowJob p = r.createProject(WorkflowJob.class, "p");
62+
p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry(registry: [url: 'https://docker.my.com/'], toolName: 'irrelevant') {}}", true));
63+
r.buildAndAssertSuccess(p);
64+
p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry(registry: [url: 'https://docker.my.com/']) {}}", true));
65+
r.buildAndAssertSuccess(p);
66+
p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry([url: 'https://docker.my.com/']) {}}", true));
67+
r.buildAndAssertSuccess(p);
68+
// and new, just in case SnippetizerTester is faking it:
69+
p.setDefinition(new CpsFlowDefinition("node {withDockerRegistry(url: 'https://docker.my.com/') {}}", true));
70+
r.buildAndAssertSuccess(p);
71+
}
72+
{ // UI form.
73+
IdCredentials registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "pass");
74+
CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials);
75+
StepConfigTester sct = new StepConfigTester(r);
76+
RegistryEndpointStep step = new RegistryEndpointStep(new DockerRegistryEndpoint("https://docker.my.com/", "registryCreds"));
77+
step = sct.configRoundTrip(step);
78+
DockerRegistryEndpoint registry = step.getRegistry();
79+
assertNotNull(registry);
80+
assertEquals("https://docker.my.com/", registry.getUrl());
81+
assertEquals("registryCreds", registry.getCredentialsId());
82+
// TODO check toolName
83+
}
7084
}
7185

7286
}

0 commit comments

Comments
 (0)