From 081caddf6554d28d535c4bc59f979a357ffda170 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Fri, 28 Jul 2023 12:22:50 -0600 Subject: [PATCH 01/27] Fix redirect when submitting cloud changes --- core/src/main/java/hudson/slaves/Cloud.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 6ec3ed3b489d..d1fcf8798ea1 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -331,7 +331,7 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro j.clouds.replace(this, result); j.save(); // take the user back to the cloud top page. - return FormApply.success("."); + return FormApply.success(".."); } public Cloud reconfigure(@NonNull final StaplerRequest req, JSONObject form) throws Descriptor.FormException { From cb2a5fde524f6a4c198cf7ea252df121674f044f Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Sat, 29 Jul 2023 00:18:33 -0600 Subject: [PATCH 02/27] update comment --- core/src/main/java/hudson/slaves/Cloud.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index d1fcf8798ea1..380db7782fe7 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -330,7 +330,7 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro } j.clouds.replace(this, result); j.save(); - // take the user back to the cloud top page. + // take the user back to the root clouds page. return FormApply.success(".."); } From 1741953fb474b24b49cd73f89a96ae74d33cb220 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Fri, 11 Aug 2023 17:08:17 -0600 Subject: [PATCH 03/27] test cloud name change --- .../test/java/hudson/slaves/CloudTest.java | 23 ++++++++++++++++++- .../slaves/CloudTest/ACloud/config.jelly | 6 +++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index 7ad4dff33aa6..a872aac5e9a4 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -11,6 +11,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.model.Action; import hudson.model.Computer; +import hudson.model.Descriptor; import hudson.model.Label; import hudson.security.Permission; import hudson.security.SidACL; @@ -21,13 +22,16 @@ import jenkins.model.Jenkins; import jenkins.model.TransientActionFactory; import org.acegisecurity.acls.sid.Sid; +import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlTextInput; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.TestExtension; import org.jvnet.hudson.test.WithoutJenkins; +import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerResponse; public class CloudTest { @@ -85,9 +89,22 @@ public void cloudNameIsEncodedInGetUrl() { assertEquals("Cloud name is encoded in Cloud#getUrl", "cloud/..%2F..%2Fgibberish/", aCloud.getUrl()); } + @Test + public void changeCloudName() throws Exception { + ACloud aCloud = new ACloud("a", "0"); + j.jenkins.clouds.add(aCloud); + HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); + HtmlTextInput input = form.getInputByName("_.name"); + input.setText("b"); + j.submit(form); + ACloud actual = j.jenkins.clouds.get(ACloud.class); + assertEquals("b", actual.getDisplayName()); + } + public static final class ACloud extends AbstractCloudImpl { - protected ACloud(String name, String instanceCapStr) { + @DataBoundConstructor + public ACloud(String name, String instanceCapStr) { super(name, instanceCapStr); } @@ -98,6 +115,10 @@ protected ACloud(String name, String instanceCapStr) { @Override public boolean canProvision(Label label) { return false; } + + @TestExtension + public static class DescriptorImpl extends Descriptor { + } } @TestExtension diff --git a/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly b/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly new file mode 100644 index 000000000000..ffd4ef80aa2f --- /dev/null +++ b/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly @@ -0,0 +1,6 @@ + + + + + + From a0a3e9cc44a5cbe018aa2dc4a0b2273833da54c5 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Tue, 15 Aug 2023 00:14:40 -0600 Subject: [PATCH 04/27] add separate page for cloud rename --- core/src/main/java/hudson/slaves/Cloud.java | 49 +++++++++++++++++-- .../hudson/slaves/Cloud/rename.jelly | 46 +++++++++++++++++ .../hudson/slaves/Cloud/sidepanel.jelly | 3 ++ .../jenkins/agents/Messages.properties | 1 + 4 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 core/src/main/resources/hudson/slaves/Cloud/rename.jelly diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 380db7782fe7..4bf79115d36d 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -311,10 +311,10 @@ public HttpResponse doDoDelete() throws IOException { } /** - * Accepts the update to the node configuration. + * Accepts the update to the node name. */ @POST - public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { checkPermission(Jenkins.ADMINISTER); Jenkins j = Jenkins.get(); @@ -330,8 +330,49 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro } j.clouds.replace(this, result); j.save(); - // take the user back to the root clouds page. - return FormApply.success(".."); + + String reqPath = req.getOriginalRequestURI(); + String[] uriTokens = reqPath.replaceFirst("^/", "").split("/"); + if (uriTokens.length < 3 || !"rename".equals(uriTokens[uriTokens.length - 1])) { + // We should never be here, expecting URI format jenkins/cloud/name/configSubmit + throw new ServletException("Expected cloud rename URI: " + reqPath); + } + String cloudId = uriTokens[uriTokens.length - 2]; + if (this.name.equals(cloudId)) { + // cloud name being used in URI + if (!proposedName.equals(this.name)) { + // name changed + cloudId = proposedName; + } else { + cloudId = this.name; + } + } + + // take the user to the renamed cloud top page. + return FormApply.success("../" + cloudId); + } + + /** + * Accepts the update to the node configuration. Node name is not allowed to be changed. + */ + @POST + public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + checkPermission(Jenkins.ADMINISTER); + + Jenkins j = Jenkins.get(); + Cloud cloud = j.getCloud(this.name); + if (cloud == null) { + throw new ServletException("No such cloud " + this.name); + } + Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); + String proposedName = result.name; + if (!proposedName.equals(this.name)) { + throw new Descriptor.FormException(jenkins.agents.Messages.CloudSet_DoNotRename(), "name"); + } + j.clouds.replace(this, result); + j.save(); + // take the user back to the cloud top page. + return FormApply.success("."); } public Cloud reconfigure(@NonNull final StaplerRequest req, JSONObject form) throws Descriptor.FormException { diff --git a/core/src/main/resources/hudson/slaves/Cloud/rename.jelly b/core/src/main/resources/hudson/slaves/Cloud/rename.jelly new file mode 100644 index 000000000000..61cfa1e5c17d --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/rename.jelly @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly index 551560f93d3e..8d1b15852ec5 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly @@ -30,6 +30,9 @@ THE SOFTWARE. + diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index 11a27f40642c..348c3be06860 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -1,6 +1,7 @@ CloudSet.DisplayName=Clouds CloudSet.CloudAlreadyExists=Cloud called ‘{0}’ already exists CloudSet.SpecifyCloudToCopy=Specify which cloud to copy +CloudSet.DoNotRename=Rename cloud using the "Rename" page CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. From 3d50865f910f474513960e5ba498ca4a7ead047d Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Tue, 15 Aug 2023 10:14:42 -0600 Subject: [PATCH 05/27] tests cloud name change --- test/src/test/java/hudson/slaves/CloudTest.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index a872aac5e9a4..a0c60f35c599 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -22,6 +23,7 @@ import jenkins.model.Jenkins; import jenkins.model.TransientActionFactory; import org.acegisecurity.acls.sid.Sid; +import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlTextInput; @@ -90,10 +92,11 @@ public void cloudNameIsEncodedInGetUrl() { } @Test + @Issue("JENKINS-71737") public void changeCloudName() throws Exception { ACloud aCloud = new ACloud("a", "0"); j.jenkins.clouds.add(aCloud); - HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); + HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "rename").getFormByName("config"); HtmlTextInput input = form.getInputByName("_.name"); input.setText("b"); j.submit(form); @@ -101,6 +104,18 @@ public void changeCloudName() throws Exception { assertEquals("b", actual.getDisplayName()); } + @Test + @Issue("JENKINS-71737") + public void changeCloudNameinConfig() throws Exception { + ACloud aCloud = new ACloud("a", "0"); + j.jenkins.clouds.add(aCloud); + HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); + HtmlTextInput input = form.getInputByName("_.name"); + input.setText("b"); + Exception ex = assertThrows(FailingHttpStatusCodeException.class, () -> j.submit(form)); + assertTrue(ex.getMessage().contains("Bad Request")); + } + public static final class ACloud extends AbstractCloudImpl { @DataBoundConstructor From 29ad0358bf0e755f8d7df0f94b3ae96200abf1f6 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Tue, 15 Aug 2023 10:14:56 -0600 Subject: [PATCH 06/27] block using apply in cloud rename --- core/src/main/java/hudson/slaves/Cloud.java | 6 +++++- core/src/main/resources/jenkins/agents/Messages.properties | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 4bf79115d36d..57982233cc2b 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -317,6 +317,10 @@ public HttpResponse doDoDelete() throws IOException { public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { checkPermission(Jenkins.ADMINISTER); + if (FormApply.isApply(req)) { + throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_CannotApplyRename(), "name"); + } + Jenkins j = Jenkins.get(); Cloud cloud = j.getCloud(this.name); if (cloud == null) { @@ -367,7 +371,7 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); String proposedName = result.name; if (!proposedName.equals(this.name)) { - throw new Descriptor.FormException(jenkins.agents.Messages.CloudSet_DoNotRename(), "name"); + throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_DoNotRename(), "name"); } j.clouds.replace(this, result); j.save(); diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index 348c3be06860..cb9935eb6b68 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -1,7 +1,8 @@ CloudSet.DisplayName=Clouds CloudSet.CloudAlreadyExists=Cloud called ‘{0}’ already exists CloudSet.SpecifyCloudToCopy=Specify which cloud to copy -CloudSet.DoNotRename=Rename cloud using the "Rename" page CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. +Cloud.DoNotRename=Rename cloud using the "Rename" page. +Cloud.CannotApplyRename=Cannot "apply" cloud rename, use "save". From ff3cbba83433872de04313e9dc6ecb6426afcb2d Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Tue, 15 Aug 2023 12:13:55 -0600 Subject: [PATCH 07/27] fix comments --- core/src/main/java/hudson/slaves/Cloud.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 57982233cc2b..2bcaf107436e 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -338,7 +338,7 @@ public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOE String reqPath = req.getOriginalRequestURI(); String[] uriTokens = reqPath.replaceFirst("^/", "").split("/"); if (uriTokens.length < 3 || !"rename".equals(uriTokens[uriTokens.length - 1])) { - // We should never be here, expecting URI format jenkins/cloud/name/configSubmit + // We should never be here, expecting URI format jenkins/cloud/name/rename throw new ServletException("Expected cloud rename URI: " + reqPath); } String cloudId = uriTokens[uriTokens.length - 2]; From 108bc22ede7846aa4a1d8fec823c751e881fe3b4 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Wed, 16 Aug 2023 13:09:31 -0600 Subject: [PATCH 08/27] Remove rename change, block apply when changing name --- core/src/main/java/hudson/slaves/Cloud.java | 50 ++++--------------- .../hudson/slaves/Cloud/rename.jelly | 46 ----------------- .../hudson/slaves/Cloud/sidepanel.jelly | 3 -- .../jenkins/agents/Messages.properties | 1 - .../test/java/hudson/slaves/CloudTest.java | 16 +----- 5 files changed, 12 insertions(+), 104 deletions(-) delete mode 100644 core/src/main/resources/hudson/slaves/Cloud/rename.jelly diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 2bcaf107436e..1b9beb82278e 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -311,16 +311,12 @@ public HttpResponse doDoDelete() throws IOException { } /** - * Accepts the update to the node name. + * Accepts the update to the node configuration. */ @POST - public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { checkPermission(Jenkins.ADMINISTER); - if (FormApply.isApply(req)) { - throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_CannotApplyRename(), "name"); - } - Jenkins j = Jenkins.get(); Cloud cloud = j.getCloud(this.name); if (cloud == null) { @@ -328,17 +324,19 @@ public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOE } Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); String proposedName = result.name; - if (!proposedName.equals(this.name) - && j.getCloud(proposedName) != null) { - throw new Descriptor.FormException(jenkins.agents.Messages.CloudSet_CloudAlreadyExists(proposedName), "name"); + if (!proposedName.equals(this.name)) { + if (FormApply.isApply(req)) { + throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_CannotApplyRename(), "name"); + } else if (j.getCloud(proposedName) != null) { + throw new Descriptor.FormException(jenkins.agents.Messages.CloudSet_CloudAlreadyExists(proposedName), "name"); + } } j.clouds.replace(this, result); j.save(); - String reqPath = req.getOriginalRequestURI(); String[] uriTokens = reqPath.replaceFirst("^/", "").split("/"); - if (uriTokens.length < 3 || !"rename".equals(uriTokens[uriTokens.length - 1])) { - // We should never be here, expecting URI format jenkins/cloud/name/rename + if (uriTokens.length < 3 || !"configSubmit".equals(uriTokens[uriTokens.length - 1])) { + // We should never be here, expecting URI format jenkins/cloud/name/config throw new ServletException("Expected cloud rename URI: " + reqPath); } String cloudId = uriTokens[uriTokens.length - 2]; @@ -347,36 +345,10 @@ public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOE if (!proposedName.equals(this.name)) { // name changed cloudId = proposedName; - } else { - cloudId = this.name; } } - - // take the user to the renamed cloud top page. - return FormApply.success("../" + cloudId); - } - - /** - * Accepts the update to the node configuration. Node name is not allowed to be changed. - */ - @POST - public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { - checkPermission(Jenkins.ADMINISTER); - - Jenkins j = Jenkins.get(); - Cloud cloud = j.getCloud(this.name); - if (cloud == null) { - throw new ServletException("No such cloud " + this.name); - } - Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); - String proposedName = result.name; - if (!proposedName.equals(this.name)) { - throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_DoNotRename(), "name"); - } - j.clouds.replace(this, result); - j.save(); // take the user back to the cloud top page. - return FormApply.success("."); + return FormApply.success("../" + cloudId + '/'); } public Cloud reconfigure(@NonNull final StaplerRequest req, JSONObject form) throws Descriptor.FormException { diff --git a/core/src/main/resources/hudson/slaves/Cloud/rename.jelly b/core/src/main/resources/hudson/slaves/Cloud/rename.jelly deleted file mode 100644 index 61cfa1e5c17d..000000000000 --- a/core/src/main/resources/hudson/slaves/Cloud/rename.jelly +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly index 8d1b15852ec5..551560f93d3e 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly @@ -30,9 +30,6 @@ THE SOFTWARE. - diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index cb9935eb6b68..f8cc0b46dfed 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -4,5 +4,4 @@ CloudSet.SpecifyCloudToCopy=Specify which cloud to copy CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. -Cloud.DoNotRename=Rename cloud using the "Rename" page. Cloud.CannotApplyRename=Cannot "apply" cloud rename, use "save". diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index a0c60f35c599..635346925ed2 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -6,7 +6,6 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -23,7 +22,6 @@ import jenkins.model.Jenkins; import jenkins.model.TransientActionFactory; import org.acegisecurity.acls.sid.Sid; -import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlTextInput; @@ -96,7 +94,7 @@ public void cloudNameIsEncodedInGetUrl() { public void changeCloudName() throws Exception { ACloud aCloud = new ACloud("a", "0"); j.jenkins.clouds.add(aCloud); - HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "rename").getFormByName("config"); + HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); HtmlTextInput input = form.getInputByName("_.name"); input.setText("b"); j.submit(form); @@ -104,18 +102,6 @@ public void changeCloudName() throws Exception { assertEquals("b", actual.getDisplayName()); } - @Test - @Issue("JENKINS-71737") - public void changeCloudNameinConfig() throws Exception { - ACloud aCloud = new ACloud("a", "0"); - j.jenkins.clouds.add(aCloud); - HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); - HtmlTextInput input = form.getInputByName("_.name"); - input.setText("b"); - Exception ex = assertThrows(FailingHttpStatusCodeException.class, () -> j.submit(form)); - assertTrue(ex.getMessage().contains("Bad Request")); - } - public static final class ACloud extends AbstractCloudImpl { @DataBoundConstructor From cc7c4e1a7180a4bed070352bb4f1b0b8a941b27e Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Thu, 17 Aug 2023 09:14:42 -0600 Subject: [PATCH 09/27] Revert "Remove rename change, block apply when changing name" This reverts commit 108bc22ede7846aa4a1d8fec823c751e881fe3b4. --- core/src/main/java/hudson/slaves/Cloud.java | 50 +++++++++++++++---- .../hudson/slaves/Cloud/rename.jelly | 46 +++++++++++++++++ .../hudson/slaves/Cloud/sidepanel.jelly | 3 ++ .../jenkins/agents/Messages.properties | 1 + .../test/java/hudson/slaves/CloudTest.java | 16 +++++- 5 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 core/src/main/resources/hudson/slaves/Cloud/rename.jelly diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 1b9beb82278e..2bcaf107436e 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -311,12 +311,16 @@ public HttpResponse doDoDelete() throws IOException { } /** - * Accepts the update to the node configuration. + * Accepts the update to the node name. */ @POST - public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { checkPermission(Jenkins.ADMINISTER); + if (FormApply.isApply(req)) { + throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_CannotApplyRename(), "name"); + } + Jenkins j = Jenkins.get(); Cloud cloud = j.getCloud(this.name); if (cloud == null) { @@ -324,19 +328,17 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro } Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); String proposedName = result.name; - if (!proposedName.equals(this.name)) { - if (FormApply.isApply(req)) { - throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_CannotApplyRename(), "name"); - } else if (j.getCloud(proposedName) != null) { - throw new Descriptor.FormException(jenkins.agents.Messages.CloudSet_CloudAlreadyExists(proposedName), "name"); - } + if (!proposedName.equals(this.name) + && j.getCloud(proposedName) != null) { + throw new Descriptor.FormException(jenkins.agents.Messages.CloudSet_CloudAlreadyExists(proposedName), "name"); } j.clouds.replace(this, result); j.save(); + String reqPath = req.getOriginalRequestURI(); String[] uriTokens = reqPath.replaceFirst("^/", "").split("/"); - if (uriTokens.length < 3 || !"configSubmit".equals(uriTokens[uriTokens.length - 1])) { - // We should never be here, expecting URI format jenkins/cloud/name/config + if (uriTokens.length < 3 || !"rename".equals(uriTokens[uriTokens.length - 1])) { + // We should never be here, expecting URI format jenkins/cloud/name/rename throw new ServletException("Expected cloud rename URI: " + reqPath); } String cloudId = uriTokens[uriTokens.length - 2]; @@ -345,10 +347,36 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro if (!proposedName.equals(this.name)) { // name changed cloudId = proposedName; + } else { + cloudId = this.name; } } + + // take the user to the renamed cloud top page. + return FormApply.success("../" + cloudId); + } + + /** + * Accepts the update to the node configuration. Node name is not allowed to be changed. + */ + @POST + public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + checkPermission(Jenkins.ADMINISTER); + + Jenkins j = Jenkins.get(); + Cloud cloud = j.getCloud(this.name); + if (cloud == null) { + throw new ServletException("No such cloud " + this.name); + } + Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); + String proposedName = result.name; + if (!proposedName.equals(this.name)) { + throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_DoNotRename(), "name"); + } + j.clouds.replace(this, result); + j.save(); // take the user back to the cloud top page. - return FormApply.success("../" + cloudId + '/'); + return FormApply.success("."); } public Cloud reconfigure(@NonNull final StaplerRequest req, JSONObject form) throws Descriptor.FormException { diff --git a/core/src/main/resources/hudson/slaves/Cloud/rename.jelly b/core/src/main/resources/hudson/slaves/Cloud/rename.jelly new file mode 100644 index 000000000000..61cfa1e5c17d --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/rename.jelly @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly index 551560f93d3e..8d1b15852ec5 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly @@ -30,6 +30,9 @@ THE SOFTWARE. + diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index f8cc0b46dfed..cb9935eb6b68 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -4,4 +4,5 @@ CloudSet.SpecifyCloudToCopy=Specify which cloud to copy CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. +Cloud.DoNotRename=Rename cloud using the "Rename" page. Cloud.CannotApplyRename=Cannot "apply" cloud rename, use "save". diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index 635346925ed2..a0c60f35c599 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -22,6 +23,7 @@ import jenkins.model.Jenkins; import jenkins.model.TransientActionFactory; import org.acegisecurity.acls.sid.Sid; +import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlTextInput; @@ -94,7 +96,7 @@ public void cloudNameIsEncodedInGetUrl() { public void changeCloudName() throws Exception { ACloud aCloud = new ACloud("a", "0"); j.jenkins.clouds.add(aCloud); - HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); + HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "rename").getFormByName("config"); HtmlTextInput input = form.getInputByName("_.name"); input.setText("b"); j.submit(form); @@ -102,6 +104,18 @@ public void changeCloudName() throws Exception { assertEquals("b", actual.getDisplayName()); } + @Test + @Issue("JENKINS-71737") + public void changeCloudNameinConfig() throws Exception { + ACloud aCloud = new ACloud("a", "0"); + j.jenkins.clouds.add(aCloud); + HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); + HtmlTextInput input = form.getInputByName("_.name"); + input.setText("b"); + Exception ex = assertThrows(FailingHttpStatusCodeException.class, () -> j.submit(form)); + assertTrue(ex.getMessage().contains("Bad Request")); + } + public static final class ACloud extends AbstractCloudImpl { @DataBoundConstructor From e3ef831094880b3d399581ce94e8b3f9d31d23a8 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Sat, 26 Aug 2023 09:04:38 -0600 Subject: [PATCH 10/27] Add Renamable interface, generalize TransientActionFactoryImpl --- .../main/java/hudson/model/AbstractItem.java | 5 +- .../src/main/java/hudson/model/Renamable.java | 57 ++++++++++ core/src/main/java/hudson/slaves/Cloud.java | 101 ++++++++++-------- .../main/java/jenkins/model/RenameAction.java | 10 +- .../{rename.jelly => confirm-rename.jelly} | 25 ++--- .../slaves/Cloud/confirm-rename.properties | 25 +++++ .../slaves/Cloud/confirm-rename_de.properties | 3 + .../slaves/Cloud/confirm-rename_fr.properties | 1 + .../slaves/Cloud/confirm-rename_it.properties | 26 +++++ .../slaves/Cloud/confirm-rename_ja.properties | 25 +++++ .../slaves/Cloud/confirm-rename_pl.properties | 25 +++++ .../Cloud/confirm-rename_pt_BR.properties | 25 +++++ .../slaves/Cloud/confirm-rename_ru.properties | 25 +++++ .../slaves/Cloud/confirm-rename_tr.properties | 3 + .../hudson/slaves/Cloud/sidepanel.jelly | 4 +- .../jenkins/agents/Messages.properties | 4 +- .../test/java/hudson/slaves/CloudTest.java | 30 +++--- .../slaves/CloudTest/ACloud/config.jelly | 6 -- 18 files changed, 310 insertions(+), 90 deletions(-) create mode 100644 core/src/main/java/hudson/model/Renamable.java rename core/src/main/resources/hudson/slaves/Cloud/{rename.jelly => confirm-rename.jelly} (63%) create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_fr.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pl.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties create mode 100644 core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties delete mode 100644 test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java index 92900e678445..644fae213650 100644 --- a/core/src/main/java/hudson/model/AbstractItem.java +++ b/core/src/main/java/hudson/model/AbstractItem.java @@ -111,7 +111,7 @@ // Item doesn't necessarily have to be Actionable, but // Java doesn't let multiple inheritance. @ExportedBean -public abstract class AbstractItem extends Actionable implements Item, HttpDeletable, AccessControlled, DescriptorByNameOwner, StaplerProxy { +public abstract class AbstractItem extends Actionable implements Item, HttpDeletable, AccessControlled, DescriptorByNameOwner, StaplerProxy, Renamable { private static final Logger LOGGER = Logger.getLogger(AbstractItem.class.getName()); @@ -245,6 +245,7 @@ protected void doSetName(String name) { * @see #renameTo * @since 2.110 */ + @Override public boolean isNameEditable() { return false; } @@ -254,6 +255,7 @@ public boolean isNameEditable() { */ @RequirePOST @Restricted(NoExternalUse.class) + @Override public HttpResponse doConfirmRename(@QueryParameter String newName) throws IOException { newName = newName == null ? null : newName.trim(); FormValidation validationError = doCheckNewName(newName); @@ -274,6 +276,7 @@ public HttpResponse doConfirmRename(@QueryParameter String newName) throws IOExc * {@link FormValidation#error} with a message explaining the problem. */ @Restricted(NoExternalUse.class) + @Override public @NonNull FormValidation doCheckNewName(@QueryParameter String newName) { if (!isNameEditable()) { diff --git a/core/src/main/java/hudson/model/Renamable.java b/core/src/main/java/hudson/model/Renamable.java new file mode 100644 index 000000000000..0bdf086e33b5 --- /dev/null +++ b/core/src/main/java/hudson/model/Renamable.java @@ -0,0 +1,57 @@ +/* + * The MIT License + * + * Copyright 2023 CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package hudson.model; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.util.FormValidation; +import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.QueryParameter; + +public interface Renamable { + + /** + * Controls whether the default rename action is available for this object. + * + * @return whether the name can be modified by a user + * @since TODO + */ + boolean isNameEditable(); + + /** + * Renames the object + * + * @since TODO + */ + HttpResponse doConfirmRename(@QueryParameter String newName) throws Exception; + + /** + * Controls whether the default rename action is available. + * + * @return whether object name can be modified by a user + * @since TODO + */ + @NonNull + FormValidation doCheckNewName(@QueryParameter String newName); +} diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 2bcaf107436e..615af8c1b2d4 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -30,6 +30,7 @@ import hudson.DescriptorExtensionList; import hudson.Extension; import hudson.ExtensionPoint; +import hudson.Functions; import hudson.Util; import hudson.init.InitMilestone; import hudson.init.Initializer; @@ -37,8 +38,10 @@ import hudson.model.Computer; import hudson.model.Describable; import hudson.model.Descriptor; +import hudson.model.Failure; import hudson.model.Label; import hudson.model.Node; +import hudson.model.Renamable; import hudson.model.Slave; import hudson.security.ACL; import hudson.security.AccessControlled; @@ -47,6 +50,7 @@ import hudson.slaves.NodeProvisioner.PlannedNode; import hudson.util.DescriptorList; import hudson.util.FormApply; +import hudson.util.FormValidation; import java.io.IOException; import java.util.Collection; import java.util.Objects; @@ -57,9 +61,12 @@ import org.apache.commons.lang.Validate; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.DoNotUse; +import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.HttpRedirect; import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.HttpResponses; +import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.interceptor.RequirePOST; @@ -107,7 +114,7 @@ * @see NodeProvisioner * @see AbstractCloudImpl */ -public abstract class Cloud extends Actionable implements ExtensionPoint, Describable, AccessControlled { +public abstract class Cloud extends Actionable implements ExtensionPoint, Describable, AccessControlled, Renamable { /** * Uniquely identifies this {@link Cloud} instance among other instances in {@link jenkins.model.Jenkins#clouds}. @@ -310,54 +317,68 @@ public HttpResponse doDoDelete() throws IOException { return new HttpRedirect(".."); } - /** - * Accepts the update to the node name. - */ - @POST - public HttpResponse doRename(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { - checkPermission(Jenkins.ADMINISTER); - if (FormApply.isApply(req)) { - throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_CannotApplyRename(), "name"); - } + @Override + public boolean isNameEditable() { + return false; + } - Jenkins j = Jenkins.get(); - Cloud cloud = j.getCloud(this.name); - if (cloud == null) { - throw new ServletException("No such cloud " + this.name); - } - Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); - String proposedName = result.name; - if (!proposedName.equals(this.name) - && j.getCloud(proposedName) != null) { - throw new Descriptor.FormException(jenkins.agents.Messages.CloudSet_CloudAlreadyExists(proposedName), "name"); + @RequirePOST + @Restricted(NoExternalUse.class) + @Override + public HttpResponse doConfirmRename(@QueryParameter String newName) throws IOException, ServletException, Descriptor.FormException { + newName = newName == null ? null : newName.trim(); + FormValidation validationError = doCheckNewName(newName); + if (validationError.kind != FormValidation.Kind.OK) { + throw new Failure(validationError.getMessage()); } - j.clouds.replace(this, result); - j.save(); + this.name = newName; + + // take the user to the renamed cloud top page. + return HttpResponses.redirectTo("../" + Functions.encode(newName)); + } - String reqPath = req.getOriginalRequestURI(); - String[] uriTokens = reqPath.replaceFirst("^/", "").split("/"); - if (uriTokens.length < 3 || !"rename".equals(uriTokens[uriTokens.length - 1])) { - // We should never be here, expecting URI format jenkins/cloud/name/rename - throw new ServletException("Expected cloud rename URI: " + reqPath); + @NonNull + @Restricted(NoExternalUse.class) + @Override + public FormValidation doCheckNewName(String newName) { + if (!isNameEditable()) { + return FormValidation.error("Trying to rename an item that does not support this operation."); } - String cloudId = uriTokens[uriTokens.length - 2]; - if (this.name.equals(cloudId)) { - // cloud name being used in URI - if (!proposedName.equals(this.name)) { - // name changed - cloudId = proposedName; - } else { - cloudId = this.name; + checkPermission(Jenkins.ADMINISTER); + + newName = newName == null ? null : newName.trim(); + + try { + Jenkins.checkGoodName(newName); + assert newName != null; // Would have thrown Failure + if (newName.equals(name)) { + return FormValidation.warning(hudson.model.Messages.AbstractItem_NewNameUnchanged()); } + if (Jenkins.get().getCloud(newName) != null) { + return FormValidation.warning(jenkins.agents.Messages.CloudSet_CloudAlreadyExists(newName)); + } + checkRename(newName); + } catch (Failure e) { + return FormValidation.error(e.getMessage()); } + return FormValidation.ok(); + } + + /** + * Allows subclasses to block renames for domain-specific reasons. Generic validation of the new name + * (e.g., null checking, checking for illegal characters, and checking that the name is not in use) + * always happens prior to calling this method. + * + * @param newName the new name for the item + * @throws Failure if the rename should be blocked + */ + protected void checkRename(@NonNull String newName) throws Failure { - // take the user to the renamed cloud top page. - return FormApply.success("../" + cloudId); } /** - * Accepts the update to the node configuration. Node name is not allowed to be changed. + * Accepts the update to the node configuration. To change node name see {@link #doConfirmRename(String)}. */ @POST public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { @@ -369,10 +390,6 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro throw new ServletException("No such cloud " + this.name); } Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); - String proposedName = result.name; - if (!proposedName.equals(this.name)) { - throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_DoNotRename(), "name"); - } j.clouds.replace(this, result); j.save(); // take the user back to the cloud top page. diff --git a/core/src/main/java/jenkins/model/RenameAction.java b/core/src/main/java/jenkins/model/RenameAction.java index 37a75c75862d..206e5fd3bb40 100644 --- a/core/src/main/java/jenkins/model/RenameAction.java +++ b/core/src/main/java/jenkins/model/RenameAction.java @@ -25,8 +25,8 @@ package jenkins.model; import hudson.Extension; -import hudson.model.AbstractItem; import hudson.model.Action; +import hudson.model.Renamable; import java.util.Collection; import java.util.Collections; import java.util.Set; @@ -52,15 +52,15 @@ public String getUrlName() { } @Extension - public static class TransientActionFactoryImpl extends TransientActionFactory { + public static class TransientActionFactoryImpl extends TransientActionFactory { @Override - public Class type() { - return AbstractItem.class; + public Class type() { + return Renamable.class; } @Override - public Collection createFor(AbstractItem target) { + public Collection createFor(Renamable target) { if (target.isNameEditable()) { return Set.of(new RenameAction()); } else { diff --git a/core/src/main/resources/hudson/slaves/Cloud/rename.jelly b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly similarity index 63% rename from core/src/main/resources/hudson/slaves/Cloud/rename.jelly rename to core/src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly index 61cfa1e5c17d..a9bec562ffdf 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/rename.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly @@ -1,7 +1,7 @@ - - - - + + + + - - - - - - +

${%DescribeRename(it.pronoun, it.name)}

+ + + - - + - +
diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties new file mode 100644 index 000000000000..bcdc4a32d764 --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2018 CloudBees, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +DescribeRename=Rename {0} {1} +NewName=New Name +Rename=Rename diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties new file mode 100644 index 000000000000..8fd89ed115e2 --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties @@ -0,0 +1,3 @@ +DescribeRename={0} {1} umbenennen +NewName=Neuer Name +Rename=Umbenennen diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_fr.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_fr.properties new file mode 100644 index 000000000000..85badf43445c --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_fr.properties @@ -0,0 +1 @@ +Rename=Renommer diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties new file mode 100644 index 000000000000..0240a1c0cd36 --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties @@ -0,0 +1,26 @@ +# The MIT License +# +# Italian localization plugin for Jenkins +# Copyright © 2020 Alessandro Menti +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +DescribeRename=Rinomina {0} in {1} +NewName=Nuovo nome +Rename=Rinomina diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties new file mode 100644 index 000000000000..6ad646ee86a0 --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2021 Takashi Harano +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +DescribeRename=名前の変更 {0} {1} +NewName=新しい名前 +Rename=名前の変更 diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pl.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pl.properties new file mode 100644 index 000000000000..b227beb31b8e --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pl.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2019, Damian Szczepanik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Rename=Zmień nazwę +DescribeRename=Zmień nazwę {0} +NewName=Nowa nazwa diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties new file mode 100644 index 000000000000..ef6a97b84584 --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +DescribeRename=Renomear {0} {1} +Rename=Renomear +NewName=Novo nome diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties new file mode 100644 index 000000000000..5813915a6e7e --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2022 CloudBees, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +DescribeRename=Переименовать {0} {1} +NewName=Новое имя +Rename=Переименовать diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties new file mode 100644 index 000000000000..7a545cc22345 --- /dev/null +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties @@ -0,0 +1,3 @@ +DescribeRename={1} {0}sinin Adını Değiştir +NewName=Yeni Ad +Rename=Adını Değiştir diff --git a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly index 8d1b15852ec5..3aa1b0131c16 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly @@ -30,8 +30,8 @@ THE SOFTWARE. - diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index cb9935eb6b68..54bcff8653ba 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -3,6 +3,4 @@ CloudSet.CloudAlreadyExists=Cloud called ‘{0}’ already exists CloudSet.SpecifyCloudToCopy=Specify which cloud to copy CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds -CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. -Cloud.DoNotRename=Rename cloud using the "Rename" page. -Cloud.CannotApplyRename=Cannot "apply" cloud rename, use "save". +CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. \ No newline at end of file diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index a0c60f35c599..9d450b3ed57b 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -6,7 +6,6 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -21,9 +20,9 @@ import java.util.Collection; import java.util.Collections; import jenkins.model.Jenkins; +import jenkins.model.RenameAction; import jenkins.model.TransientActionFactory; import org.acegisecurity.acls.sid.Sid; -import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlTextInput; @@ -67,7 +66,8 @@ public void ui() throws Exception { assertThat(aCloud.getAllActions(), containsInAnyOrder( instanceOf(TaskCloudAction.class), - instanceOf(ReportingCloudAction.class) + instanceOf(ReportingCloudAction.class), + instanceOf(RenameAction.class) )); HtmlPage page = j.createWebClient().goTo(aCloud.getUrl()); @@ -78,6 +78,7 @@ public void ui() throws Exception { assertThat(out, containsString("Task Action")); // TaskCloudAction assertThat(out, containsString("Sidepanel action box.")); // TaskCloudAction/box.jelly assertThat(out, containsString("Report Here")); // ReportingCloudAction/summary.jelly + assertThat(out, containsString("Rename")); // confirm-rename.jelly HtmlPage actionPage = page.getAnchorByText("Task Action").click(); out = actionPage.getWebResponse().getContentAsString(); @@ -96,26 +97,16 @@ public void cloudNameIsEncodedInGetUrl() { public void changeCloudName() throws Exception { ACloud aCloud = new ACloud("a", "0"); j.jenkins.clouds.add(aCloud); - HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "rename").getFormByName("config"); - HtmlTextInput input = form.getInputByName("_.name"); + JenkinsRule.WebClient webClient = j.createWebClient(); + HtmlPage page = webClient.goTo(aCloud.getUrl() + "confirm-rename"); + HtmlForm form = page.getFormByName("config"); + HtmlTextInput input = form.getInputByName("newName"); input.setText("b"); j.submit(form); ACloud actual = j.jenkins.clouds.get(ACloud.class); assertEquals("b", actual.getDisplayName()); } - @Test - @Issue("JENKINS-71737") - public void changeCloudNameinConfig() throws Exception { - ACloud aCloud = new ACloud("a", "0"); - j.jenkins.clouds.add(aCloud); - HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); - HtmlTextInput input = form.getInputByName("_.name"); - input.setText("b"); - Exception ex = assertThrows(FailingHttpStatusCodeException.class, () -> j.submit(form)); - assertTrue(ex.getMessage().contains("Bad Request")); - } - public static final class ACloud extends AbstractCloudImpl { @DataBoundConstructor @@ -131,6 +122,11 @@ public ACloud(String name, String instanceCapStr) { return false; } + @Override + public boolean isNameEditable() { + return true; + } + @TestExtension public static class DescriptorImpl extends Descriptor { } diff --git a/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly b/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly deleted file mode 100644 index ffd4ef80aa2f..000000000000 --- a/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - From 7a96cd6ef8d578c999e7bb802697189c4ad75f22 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Wed, 30 Aug 2023 16:35:11 -0600 Subject: [PATCH 11/27] change isNameEditable default to true --- core/src/main/java/hudson/slaves/Cloud.java | 2 +- test/src/test/java/hudson/slaves/CloudTest.java | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 615af8c1b2d4..088decb91b1f 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -320,7 +320,7 @@ public HttpResponse doDoDelete() throws IOException { @Override public boolean isNameEditable() { - return false; + return true; } @RequirePOST diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index 9d450b3ed57b..4ded2072cfe2 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -122,11 +122,6 @@ public ACloud(String name, String instanceCapStr) { return false; } - @Override - public boolean isNameEditable() { - return true; - } - @TestExtension public static class DescriptorImpl extends Descriptor { } From b8e7f84ba83559d2ba0899c3fd865b1323ee3b27 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Wed, 30 Aug 2023 17:25:31 -0600 Subject: [PATCH 12/27] update jelly --- .../src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly | 2 +- .../resources/hudson/slaves/Cloud/confirm-rename.properties | 2 +- .../resources/hudson/slaves/Cloud/confirm-rename_de.properties | 2 +- .../resources/hudson/slaves/Cloud/confirm-rename_it.properties | 2 +- .../resources/hudson/slaves/Cloud/confirm-rename_ja.properties | 2 +- .../hudson/slaves/Cloud/confirm-rename_pt_BR.properties | 2 +- .../resources/hudson/slaves/Cloud/confirm-rename_ru.properties | 2 +- .../resources/hudson/slaves/Cloud/confirm-rename_tr.properties | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly index a9bec562ffdf..753537e2bd29 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.jelly @@ -28,7 +28,7 @@ THE SOFTWARE. -

${%DescribeRename(it.pronoun, it.name)}

+

${%DescribeRename(it.name)}

diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties index bcdc4a32d764..feda6b5f747e 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename.properties @@ -20,6 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -DescribeRename=Rename {0} {1} +DescribeRename=Rename {0} NewName=New Name Rename=Rename diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties index 8fd89ed115e2..1edaa21591c2 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_de.properties @@ -1,3 +1,3 @@ -DescribeRename={0} {1} umbenennen +DescribeRename={0} umbenennen NewName=Neuer Name Rename=Umbenennen diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties index 0240a1c0cd36..195c0781afb6 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_it.properties @@ -21,6 +21,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -DescribeRename=Rinomina {0} in {1} +DescribeRename=Rinomina {0} NewName=Nuovo nome Rename=Rinomina diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties index 6ad646ee86a0..5c8ed9386009 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ja.properties @@ -20,6 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -DescribeRename=名前の変更 {0} {1} +DescribeRename=名前の変更 {0} NewName=新しい名前 Rename=名前の変更 diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties index ef6a97b84584..5697d0ef0e95 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_pt_BR.properties @@ -20,6 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -DescribeRename=Renomear {0} {1} +DescribeRename=Renomear {0} Rename=Renomear NewName=Novo nome diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties index 5813915a6e7e..4b5411d3f622 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_ru.properties @@ -20,6 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -DescribeRename=Переименовать {0} {1} +DescribeRename=Переименовать {0} NewName=Новое имя Rename=Переименовать diff --git a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties index 7a545cc22345..ec0f297bbe8a 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties +++ b/core/src/main/resources/hudson/slaves/Cloud/confirm-rename_tr.properties @@ -1,3 +1,3 @@ -DescribeRename={1} {0}sinin Adını Değiştir +DescribeRename={0} Adını Değiştir NewName=Yeni Ad Rename=Adını Değiştir From aec2de17e0ed51c5473ccf2fb4225976a0f85445 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Wed, 30 Aug 2023 21:55:09 -0600 Subject: [PATCH 13/27] add check for improper name change --- core/src/main/java/hudson/slaves/Cloud.java | 3 +++ .../resources/jenkins/agents/Messages.properties | 3 ++- test/src/test/java/hudson/slaves/CloudTest.java | 14 ++++++++++++++ .../hudson/slaves/CloudTest/ACloud/config.jelly | 6 ++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 088decb91b1f..11b62b18ef65 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -390,6 +390,9 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro throw new ServletException("No such cloud " + this.name); } Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); + if (!(result.name).equals(this.name)) { + throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_DoNotRename(), "name"); + } j.clouds.replace(this, result); j.save(); // take the user back to the cloud top page. diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index 54bcff8653ba..046dc328f95a 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -3,4 +3,5 @@ CloudSet.CloudAlreadyExists=Cloud called ‘{0}’ already exists CloudSet.SpecifyCloudToCopy=Specify which cloud to copy CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds -CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. \ No newline at end of file +CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. +Cloud.DoNotRename=Rename cloud using the "Rename" page. \ No newline at end of file diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index 4ded2072cfe2..7a81f9678820 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -23,6 +24,7 @@ import jenkins.model.RenameAction; import jenkins.model.TransientActionFactory; import org.acegisecurity.acls.sid.Sid; +import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlTextInput; @@ -107,6 +109,18 @@ public void changeCloudName() throws Exception { assertEquals("b", actual.getDisplayName()); } + @Test + @Issue("JENKINS-71737") + public void changeCloudNameinConfig() throws Exception { + ACloud aCloud = new ACloud("a", "0"); + j.jenkins.clouds.add(aCloud); + HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); + HtmlTextInput input = form.getInputByName("_.name"); + input.setText("b"); + Exception ex = assertThrows(FailingHttpStatusCodeException.class, () -> j.submit(form)); + assertTrue(ex.getMessage().contains("Bad Request")); + } + public static final class ACloud extends AbstractCloudImpl { @DataBoundConstructor diff --git a/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly b/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly new file mode 100644 index 000000000000..c1a1a18a9534 --- /dev/null +++ b/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From d5b6dcd38356816472b76343151a3c5d6c120af6 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Thu, 31 Aug 2023 10:09:37 -0600 Subject: [PATCH 14/27] hide sidepanel link if name not editable --- .../hudson/slaves/Cloud/sidepanel.jelly | 8 ++-- .../test/java/hudson/slaves/CloudTest.java | 46 ++++++++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly index 3aa1b0131c16..b597a76d3291 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly @@ -30,9 +30,11 @@ THE SOFTWARE. - + + + diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index 7a81f9678820..d8b4956eb7aa 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThrows; @@ -121,7 +122,33 @@ public void changeCloudNameinConfig() throws Exception { assertTrue(ex.getMessage().contains("Bad Request")); } - public static final class ACloud extends AbstractCloudImpl { + @Test + @Issue("JENKINS-71737") + public void uiNoNameChange() throws Exception { + CloudNameImmutable cloudFixedName = new CloudNameImmutable("Name Fixed", "0"); + j.jenkins.clouds.add(cloudFixedName); + + assertThat(cloudFixedName.getAllActions(), containsInAnyOrder( + instanceOf(TaskCloudAction.class), + instanceOf(ReportingCloudAction.class) + )); + + HtmlPage page = j.createWebClient().goTo(cloudFixedName.getUrl()); + String out = page.getWebResponse().getContentAsString(); + assertThat(out, containsString("Cloud Name Fixed")); // index.jelly + assertThat(out, containsString("Top cloud view.")); // top.jelly + assertThat(out, containsString("custom cloud main groovy")); // main.jelly + assertThat(out, containsString("Task Action")); // TaskCloudAction + assertThat(out, containsString("Sidepanel action box.")); // TaskCloudAction/box.jelly + assertThat(out, containsString("Report Here")); // ReportingCloudAction/summary.jelly + assertThat(out, not(containsString("Rename"))); // confirm-rename.jelly + + HtmlPage actionPage = page.getAnchorByText("Task Action").click(); + out = actionPage.getWebResponse().getContentAsString(); + assertThat(out, containsString("doIndex called")); // doIndex + } + + public static class ACloud extends AbstractCloudImpl { @DataBoundConstructor public ACloud(String name, String instanceCapStr) { @@ -141,6 +168,23 @@ public static class DescriptorImpl extends Descriptor { } } + public static final class CloudNameImmutable extends ACloud { + + @DataBoundConstructor + public CloudNameImmutable(String name, String instanceCapStr) { + super(name, instanceCapStr); + } + + @Override + public boolean isNameEditable() { + return false; + } + + @TestExtension + public static class DescriptorImpl extends Descriptor { + } + } + @TestExtension public static final class CloudActionFactory extends TransientActionFactory { From a57343cb77ef16296137bac9932d7cf8bc97206e Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Thu, 31 Aug 2023 20:19:21 -0600 Subject: [PATCH 15/27] remove unnecessary sidepanel link --- .../main/resources/hudson/slaves/Cloud/sidepanel.jelly | 5 ----- test/src/test/java/hudson/slaves/CloudTest.java | 10 +++++----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly index b597a76d3291..551560f93d3e 100644 --- a/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly +++ b/core/src/main/resources/hudson/slaves/Cloud/sidepanel.jelly @@ -30,11 +30,6 @@ THE SOFTWARE. - - - diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index d8b4956eb7aa..8bb221b90de0 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -124,16 +124,16 @@ public void changeCloudNameinConfig() throws Exception { @Test @Issue("JENKINS-71737") - public void uiNoNameChange() throws Exception { - CloudNameImmutable cloudFixedName = new CloudNameImmutable("Name Fixed", "0"); - j.jenkins.clouds.add(cloudFixedName); + public void uneditableNameUI() throws Exception { + CloudNameImmutable fixedName = new CloudNameImmutable("Name Fixed", "0"); + j.jenkins.clouds.add(fixedName); - assertThat(cloudFixedName.getAllActions(), containsInAnyOrder( + assertThat(fixedName.getAllActions(), containsInAnyOrder( instanceOf(TaskCloudAction.class), instanceOf(ReportingCloudAction.class) )); - HtmlPage page = j.createWebClient().goTo(cloudFixedName.getUrl()); + HtmlPage page = j.createWebClient().goTo(fixedName.getUrl()); String out = page.getWebResponse().getContentAsString(); assertThat(out, containsString("Cloud Name Fixed")); // index.jelly assertThat(out, containsString("Top cloud view.")); // top.jelly From b7eed6f13284dc3ab849cd10b23aad1dadc3c7f1 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Wed, 6 Sep 2023 18:00:38 -0600 Subject: [PATCH 16/27] update Renamable javadoc --- core/src/main/java/hudson/model/Renamable.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/hudson/model/Renamable.java b/core/src/main/java/hudson/model/Renamable.java index 0bdf086e33b5..1ae780bc03c8 100644 --- a/core/src/main/java/hudson/model/Renamable.java +++ b/core/src/main/java/hudson/model/Renamable.java @@ -26,23 +26,30 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.util.FormValidation; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.ProtectedExternally; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.QueryParameter; +/** + * Interface used to create a dedicated page that changes the name property of an Object. + * See also {@link jenkins.model.RenameAction}. + * + * @since TODO + */ +@Restricted(ProtectedExternally.class) public interface Renamable { /** * Controls whether the default rename action is available for this object. * * @return whether the name can be modified by a user - * @since TODO */ boolean isNameEditable(); /** * Renames the object * - * @since TODO */ HttpResponse doConfirmRename(@QueryParameter String newName) throws Exception; @@ -50,7 +57,6 @@ public interface Renamable { * Controls whether the default rename action is available. * * @return whether object name can be modified by a user - * @since TODO */ @NonNull FormValidation doCheckNewName(@QueryParameter String newName); From 6c561f710069c8fc6cc14703470822800760f161 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Thu, 7 Sep 2023 20:41:20 -0600 Subject: [PATCH 17/27] silently block renaming in config page --- core/src/main/java/hudson/slaves/Cloud.java | 3 ++- core/src/main/resources/jenkins/agents/Messages.properties | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 11b62b18ef65..70ed50d11c14 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -391,7 +391,8 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro } Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); if (!(result.name).equals(this.name)) { - throw new Descriptor.FormException(jenkins.agents.Messages.Cloud_DoNotRename(), "name"); + // Do not rename the cloud in the config page. Use doConfirmRename() + result.name = this.name; } j.clouds.replace(this, result); j.save(); diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index 046dc328f95a..54bcff8653ba 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -3,5 +3,4 @@ CloudSet.CloudAlreadyExists=Cloud called ‘{0}’ already exists CloudSet.SpecifyCloudToCopy=Specify which cloud to copy CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds -CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. -Cloud.DoNotRename=Rename cloud using the "Rename" page. \ No newline at end of file +CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. \ No newline at end of file From 92489f1fcb4adde341b53fac39fb5ac6fa0ab578 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Fri, 8 Sep 2023 12:52:33 -0600 Subject: [PATCH 18/27] update test --- test/src/test/java/hudson/slaves/CloudTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index 8bb221b90de0..d9e9b7bb4d20 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -7,7 +7,6 @@ import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -25,7 +24,6 @@ import jenkins.model.RenameAction; import jenkins.model.TransientActionFactory; import org.acegisecurity.acls.sid.Sid; -import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlTextInput; @@ -118,8 +116,9 @@ public void changeCloudNameinConfig() throws Exception { HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); HtmlTextInput input = form.getInputByName("_.name"); input.setText("b"); - Exception ex = assertThrows(FailingHttpStatusCodeException.class, () -> j.submit(form)); - assertTrue(ex.getMessage().contains("Bad Request")); + j.submit(form); + ACloud actual = j.jenkins.clouds.get(ACloud.class); + assertEquals("a", actual.getDisplayName()); } @Test From b6e2fdeaa3afbc2cb0be4a44dd09ed72a9f44c8f Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Sat, 9 Sep 2023 00:31:49 -0600 Subject: [PATCH 19/27] pass name field during cloud creation --- .../jenkins/agents/CloudSet/_new.jelly | 3 ++ .../test/java/hudson/slaves/CloudTest.java | 38 ++++++++++++++++--- .../CloudTest/CloudNameImmutable/main.groovy | 3 ++ .../CloudTest/CloudNameImmutable/top.jelly | 6 +++ .../config.jelly | 0 .../CloudTest/NameInConfigCloud/main.groovy | 3 ++ .../CloudTest/NameInConfigCloud/top.jelly | 6 +++ 7 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/main.groovy create mode 100644 test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/top.jelly rename test/src/test/resources/hudson/slaves/CloudTest/{ACloud => NameInConfigCloud}/config.jelly (100%) create mode 100644 test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/main.groovy create mode 100644 test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/top.jelly diff --git a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly index 3ea4d00d6acc..d7bba38359e6 100644 --- a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly +++ b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly @@ -33,6 +33,9 @@ THE SOFTWARE.

${%New cloud}

+ + + diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index d9e9b7bb4d20..e2394368867d 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -111,13 +111,13 @@ public void changeCloudName() throws Exception { @Test @Issue("JENKINS-71737") public void changeCloudNameinConfig() throws Exception { - ACloud aCloud = new ACloud("a", "0"); - j.jenkins.clouds.add(aCloud); - HtmlForm form = j.createWebClient().goTo(aCloud.getUrl() + "configure").getFormByName("config"); + NameInConfigCloud nameCloud = new NameInConfigCloud("a", "0"); + j.jenkins.clouds.add(nameCloud); + HtmlForm form = j.createWebClient().goTo(nameCloud.getUrl() + "configure").getFormByName("config"); HtmlTextInput input = form.getInputByName("_.name"); input.setText("b"); j.submit(form); - ACloud actual = j.jenkins.clouds.get(ACloud.class); + NameInConfigCloud actual = j.jenkins.clouds.get(NameInConfigCloud.class); assertEquals("a", actual.getDisplayName()); } @@ -167,7 +167,27 @@ public static class DescriptorImpl extends Descriptor { } } - public static final class CloudNameImmutable extends ACloud { + public static final class NameInConfigCloud extends AbstractCloudImpl { + + @DataBoundConstructor + public NameInConfigCloud(String name, String instanceCapStr) { + super(name, instanceCapStr); + } + + @Override public Collection provision(Label label, int excessWorkload) { + return Collections.emptyList(); + } + + @Override public boolean canProvision(Label label) { + return false; + } + + @TestExtension + public static class DescriptorImpl extends Descriptor { + } + } + + public static final class CloudNameImmutable extends AbstractCloudImpl { @DataBoundConstructor public CloudNameImmutable(String name, String instanceCapStr) { @@ -179,6 +199,14 @@ public boolean isNameEditable() { return false; } + @Override public Collection provision(Label label, int excessWorkload) { + return Collections.emptyList(); + } + + @Override public boolean canProvision(Label label) { + return false; + } + @TestExtension public static class DescriptorImpl extends Descriptor { } diff --git a/test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/main.groovy b/test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/main.groovy new file mode 100644 index 000000000000..17e4b475580e --- /dev/null +++ b/test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/main.groovy @@ -0,0 +1,3 @@ +package hudson.slaves.CloudTest.ACloud + +text("custom cloud main groovy") diff --git a/test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/top.jelly b/test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/top.jelly new file mode 100644 index 000000000000..81bd5ea72570 --- /dev/null +++ b/test/src/test/resources/hudson/slaves/CloudTest/CloudNameImmutable/top.jelly @@ -0,0 +1,6 @@ + + + + Top cloud view. + + diff --git a/test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly b/test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/config.jelly similarity index 100% rename from test/src/test/resources/hudson/slaves/CloudTest/ACloud/config.jelly rename to test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/config.jelly diff --git a/test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/main.groovy b/test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/main.groovy new file mode 100644 index 000000000000..17e4b475580e --- /dev/null +++ b/test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/main.groovy @@ -0,0 +1,3 @@ +package hudson.slaves.CloudTest.ACloud + +text("custom cloud main groovy") diff --git a/test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/top.jelly b/test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/top.jelly new file mode 100644 index 000000000000..81bd5ea72570 --- /dev/null +++ b/test/src/test/resources/hudson/slaves/CloudTest/NameInConfigCloud/top.jelly @@ -0,0 +1,6 @@ + + + + Top cloud view. + + From 5bb029fbc6a431cff840edf7b071e913173a516c Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Sat, 9 Sep 2023 14:17:37 -0600 Subject: [PATCH 20/27] chnage cloudName to name in _new.jelly --- core/src/main/resources/jenkins/agents/CloudSet/_new.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly index d7bba38359e6..f1d8b73e5ea9 100644 --- a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly +++ b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly @@ -33,7 +33,7 @@ THE SOFTWARE.

${%New cloud}

- + From 63c36332ef84f5fe03eab08bc399b209bb02b748 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Mon, 11 Sep 2023 13:30:36 -0600 Subject: [PATCH 21/27] change to invisible text box --- core/src/main/resources/jenkins/agents/CloudSet/_new.jelly | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly index f1d8b73e5ea9..ca9a380cdfb8 100644 --- a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly +++ b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly @@ -33,9 +33,9 @@ THE SOFTWARE.

${%New cloud}

- - - + + + From bf62fc2a29d04d075e191cd5ad85be5a687e1dda Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Mon, 11 Sep 2023 13:30:50 -0600 Subject: [PATCH 22/27] remove cloudName from Cloud formdata --- core/src/main/java/jenkins/agents/CloudSet.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/jenkins/agents/CloudSet.java b/core/src/main/java/jenkins/agents/CloudSet.java index 5229dd06f18b..3ab69ad0df2f 100644 --- a/core/src/main/java/jenkins/agents/CloudSet.java +++ b/core/src/main/java/jenkins/agents/CloudSet.java @@ -226,7 +226,6 @@ private void handleNewCloudPage(Descriptor descriptor, String name, Stapl checkName(name); JSONObject formData = req.getSubmittedForm(); formData.put("name", name); - formData.put("cloudName", name); // ec2 uses that field name formData.remove("mode"); // Cloud descriptors won't have this field. req.setAttribute("instance", formData); req.setAttribute("descriptor", descriptor); From 1024b9eb344b5993fa07f7ff29a438b83aa9f9f0 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Mon, 11 Sep 2023 21:33:03 -0600 Subject: [PATCH 23/27] add cloudName back to formData --- core/src/main/java/jenkins/agents/CloudSet.java | 3 +++ core/src/main/resources/jenkins/agents/CloudSet/_new.jelly | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/core/src/main/java/jenkins/agents/CloudSet.java b/core/src/main/java/jenkins/agents/CloudSet.java index 3ab69ad0df2f..307c9167258b 100644 --- a/core/src/main/java/jenkins/agents/CloudSet.java +++ b/core/src/main/java/jenkins/agents/CloudSet.java @@ -226,6 +226,9 @@ private void handleNewCloudPage(Descriptor descriptor, String name, Stapl checkName(name); JSONObject formData = req.getSubmittedForm(); formData.put("name", name); + // multiple cloud implementations use cloudName instead of name. It is simpler to retain this field rather than + // refactor all the downstream plugins and the related tests. + formData.put("cloudName", name); formData.remove("mode"); // Cloud descriptors won't have this field. req.setAttribute("instance", formData); req.setAttribute("descriptor", descriptor); diff --git a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly index ca9a380cdfb8..667df6cb56a3 100644 --- a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly +++ b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly @@ -33,9 +33,13 @@ THE SOFTWARE.

${%New cloud}

+ + + + From 4b89c49be6088fd7c91d0606dd99b41031b1870d Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Tue, 12 Sep 2023 09:08:46 -0600 Subject: [PATCH 24/27] cleanup --- core/src/main/resources/jenkins/agents/Messages.properties | 2 +- test/src/test/java/hudson/slaves/CloudTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/jenkins/agents/Messages.properties b/core/src/main/resources/jenkins/agents/Messages.properties index 54bcff8653ba..11a27f40642c 100644 --- a/core/src/main/resources/jenkins/agents/Messages.properties +++ b/core/src/main/resources/jenkins/agents/Messages.properties @@ -3,4 +3,4 @@ CloudSet.CloudAlreadyExists=Cloud called ‘{0}’ already exists CloudSet.SpecifyCloudToCopy=Specify which cloud to copy CloudSet.NoSuchCloud=No such cloud: {0} CloudsLink.DisplayName=Clouds -CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. \ No newline at end of file +CloudsLink.Description=Add, remove, and configure cloud instances to provision agents on-demand. diff --git a/test/src/test/java/hudson/slaves/CloudTest.java b/test/src/test/java/hudson/slaves/CloudTest.java index e2394368867d..9dfd7ea73b76 100644 --- a/test/src/test/java/hudson/slaves/CloudTest.java +++ b/test/src/test/java/hudson/slaves/CloudTest.java @@ -147,7 +147,7 @@ public void uneditableNameUI() throws Exception { assertThat(out, containsString("doIndex called")); // doIndex } - public static class ACloud extends AbstractCloudImpl { + public static final class ACloud extends AbstractCloudImpl { @DataBoundConstructor public ACloud(String name, String instanceCapStr) { From 8c3d6c65b758133a150095ef68f97bfd2c91eb21 Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Tue, 12 Sep 2023 11:40:05 -0600 Subject: [PATCH 25/27] add name fields to config form data --- core/src/main/java/hudson/slaves/Cloud.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 70ed50d11c14..fec2801e3e77 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -389,7 +389,12 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro if (cloud == null) { throw new ServletException("No such cloud " + this.name); } - Cloud result = cloud.reconfigure(req, req.getSubmittedForm()); + JSONObject formData = req.getSubmittedForm(); + // add the cloud name to the submitted form data + formData.put("name", name); + // multiple cloud implementations use cloudName instead of name. + formData.put("cloudName", name); + Cloud result = cloud.reconfigure(req, formData); if (!(result.name).equals(this.name)) { // Do not rename the cloud in the config page. Use doConfirmRename() result.name = this.name; From 231db9490cbc18d035805eaee4f8010fdfa0472b Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Wed, 13 Sep 2023 16:29:21 -0600 Subject: [PATCH 26/27] remove cloudName from new cloud form data --- core/src/main/java/hudson/slaves/Cloud.java | 2 -- core/src/main/java/jenkins/agents/CloudSet.java | 3 --- core/src/main/resources/jenkins/agents/CloudSet/_new.jelly | 5 +---- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index fec2801e3e77..1c22b1fb5eec 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -392,8 +392,6 @@ public HttpResponse doConfigSubmit(StaplerRequest req, StaplerResponse rsp) thro JSONObject formData = req.getSubmittedForm(); // add the cloud name to the submitted form data formData.put("name", name); - // multiple cloud implementations use cloudName instead of name. - formData.put("cloudName", name); Cloud result = cloud.reconfigure(req, formData); if (!(result.name).equals(this.name)) { // Do not rename the cloud in the config page. Use doConfirmRename() diff --git a/core/src/main/java/jenkins/agents/CloudSet.java b/core/src/main/java/jenkins/agents/CloudSet.java index 307c9167258b..3ab69ad0df2f 100644 --- a/core/src/main/java/jenkins/agents/CloudSet.java +++ b/core/src/main/java/jenkins/agents/CloudSet.java @@ -226,9 +226,6 @@ private void handleNewCloudPage(Descriptor descriptor, String name, Stapl checkName(name); JSONObject formData = req.getSubmittedForm(); formData.put("name", name); - // multiple cloud implementations use cloudName instead of name. It is simpler to retain this field rather than - // refactor all the downstream plugins and the related tests. - formData.put("cloudName", name); formData.remove("mode"); // Cloud descriptors won't have this field. req.setAttribute("instance", formData); req.setAttribute("descriptor", descriptor); diff --git a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly index 667df6cb56a3..61f0b65bfc0f 100644 --- a/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly +++ b/core/src/main/resources/jenkins/agents/CloudSet/_new.jelly @@ -33,13 +33,10 @@ THE SOFTWARE.

${%New cloud}

- + - - - From 13bab6c5e0249618e47e31e88e8e5e9ed8a4ee9d Mon Sep 17 00:00:00 2001 From: Carroll Chiou Date: Tue, 19 Sep 2023 09:58:15 -0600 Subject: [PATCH 27/27] save to disk when changing name --- core/src/main/java/hudson/slaves/Cloud.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/hudson/slaves/Cloud.java b/core/src/main/java/hudson/slaves/Cloud.java index 1c22b1fb5eec..faf097c5ff89 100644 --- a/core/src/main/java/hudson/slaves/Cloud.java +++ b/core/src/main/java/hudson/slaves/Cloud.java @@ -333,6 +333,7 @@ public HttpResponse doConfirmRename(@QueryParameter String newName) throws IOExc throw new Failure(validationError.getMessage()); } this.name = newName; + Jenkins.get().save(); // take the user to the renamed cloud top page. return HttpResponses.redirectTo("../" + Functions.encode(newName));