diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index e30f5c390acadde493ae9b65a806eb16a06fdc4a..4ce4a3b7a39db9ac05bf9c7b02023a7c29662e5a 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -2,7 +2,8 @@ * The MIT License * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, - * Red Hat, Inc., Seiji Sogabe, Stephen Connolly, Thomas J. Black, Tom Huybrechts, CloudBees, Inc. + * Red Hat, Inc., Seiji Sogabe, Stephen Connolly, Thomas J. Black, Tom Huybrechts, + * CloudBees, Inc., Christopher Simons * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -1384,13 +1385,19 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces public void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException { checkPermission(CONFIGURE); - String name = Util.fixEmptyAndTrim(req.getSubmittedForm().getString("name")); - Jenkins.checkGoodName(name); + String proposedName = Util.fixEmptyAndTrim(req.getSubmittedForm().getString("name")); + Jenkins.checkGoodName(proposedName); Node node = getNode(); if (node == null) { throw new ServletException("No such node " + nodeName); } + + if ((!proposedName.equals(nodeName)) + && Jenkins.getActiveInstance().getNode(proposedName) != null) { + throw new FormException(Messages.ComputerSet_SlaveAlreadyExists(proposedName), "name"); + } + Node result = node.reconfigure(req, req.getSubmittedForm()); replaceBy(result); diff --git a/test/src/test/java/hudson/model/ComputerTest.java b/test/src/test/java/hudson/model/ComputerTest.java index b58b00f45e5380a80177ef0eb47d8f782f84d4da..8b6efad4138f23a7b2d4721a5d38730ef84a17e9 100644 --- a/test/src/test/java/hudson/model/ComputerTest.java +++ b/test/src/test/java/hudson/model/ComputerTest.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2015 Red Hat, Inc. + * Copyright (c) 2015 Red Hat, Inc.; Christopher Simons * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,16 +23,26 @@ */ package hudson.model; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.*; +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.html.HtmlForm; +import com.gargoylesoftware.htmlunit.html.HtmlPage; + import java.io.File; import jenkins.model.Jenkins; import hudson.slaves.DumbSlave; +import org.junit.Before; 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.JenkinsRule.WebClient; public class ComputerTest { @@ -52,4 +62,29 @@ public class ComputerTest { assertTrue("Slave log should be kept", keep.toComputer().getLogFile().exists()); } + + /** + * Verify we can't rename a node over an existing node. + */ + @Issue("JENKINS-31321") + @Test + public void testProhibitRenameOverExistingNode() throws Exception { + final String NOTE = "Rename node to name of another node should fail."; + + Node nodeA = j.createSlave("nodeA", null, null); + Node nodeB = j.createSlave("nodeB", null, null); + + WebClient wc = j.createWebClient(); + HtmlForm form = wc.getPage(nodeB, "configure").getFormByName("config"); + form.getInputByName("_.name").setValueAttribute("nodeA"); + + try { + j.submit(form); + fail(NOTE); + } catch (FailingHttpStatusCodeException e) { + assertThat(NOTE, e.getStatusCode(), equalTo(400)); + assertThat(NOTE, e.getResponse().getContentAsString(), + containsString("Slave called ‘nodeA’ already exists")); + } + } }