提交 92e81bf0 编写于 作者: S Stefan Wolf

Merge branch 'master' into aggregate-test-result

Conflicts:
	changelog.html
......@@ -54,6 +54,16 @@ Upcoming changes</a>
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image>
<li class=rfe>
Offer alternate error message for pattern-based project naming strategy.
(<a href="https://github.com/jenkinsci/jenkins/pull/914">pull request 914</a>)
</ul>
</div><!--=TRUNK-END=-->
<!-- these changes are controlled by the release process. DO NOT MODIFY -->
<div id="rc" style="display:none;"><!--=BEGIN=-->
<h3><a name=v1.532>What's new in 1.532</a> <!--=DATE=--></h3>
<ul class=image>
<li class='major bug'>
Working around a GZip compression bug in jzlib affecting transfer of certain large, repetitive artifacts.
......@@ -70,15 +80,15 @@ Upcoming changes</a>
<li class='major rfe'>
Added a new extension point to control where archived artifacts get stored.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17236">issue 17236</a>)
<li class=rfe>
Use fine-grained permissions for node manipulation via REST API &amp; CLI
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18485">issue 18485</a>)
<li class='bug'>
Make the link to the aggregated test result from the project page work.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-9637">issue 9637</a>)
</ul>
</div><!--=TRUNK-END=-->
<!-- these changes are controlled by the release process. DO NOT MODIFY -->
<div id="rc" style="display:none;"><!--=BEGIN=-->
<h3><a name=v1.531>What's new in 1.531</a> <!--=DATE=--></h3>
</div><!--=END=-->
<h3><a name=v1.531>What's new in 1.531</a> (2013/09/16)</h3>
<ul class=image>
<li class=bug>
Deleting an external run did not immediately remove it from build list, leading to errors from log rotation.
......@@ -105,7 +115,6 @@ Upcoming changes</a>
No events fired when project is enable/disable or the description is changed
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17108">issue 17108</a>)
</ul>
</div><!--=END=-->
<h3><a name=v1.530>What's new in 1.530</a> (2013/09/09)</h3>
<ul class=image>
<li class=bug>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>pom</artifactId>
<groupId>org.jenkins-ci.main</groupId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
</parent>
<artifactId>cli</artifactId>
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......@@ -102,7 +102,7 @@ THE SOFTWARE.
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-posix</artifactId>
<version>3.0.0</version>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.kohsuke</groupId>
......
......@@ -25,6 +25,7 @@
package hudson.cli;
import hudson.Extension;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.model.Slave;
import hudson.model.User;
......@@ -35,7 +36,7 @@ import org.kohsuke.args4j.CmdLineException;
/**
* @author ogondza
* @since XXX
* @since 1.526
*/
@Extension
public class CreateNodeCommand extends CLICommand {
......@@ -53,7 +54,7 @@ public class CreateNodeCommand extends CLICommand {
protected int run() throws Exception {
final Jenkins jenkins = Jenkins.getInstance();
jenkins.checkPermission(Jenkins.ADMINISTER);
jenkins.checkPermission(Computer.CREATE);
final Node newNode = (Node) Jenkins.XSTREAM2.fromXML(stdin);
......
......@@ -24,6 +24,7 @@
package hudson.cli;
import hudson.Extension;
import hudson.model.Computer;
import hudson.model.Node;
import java.io.IOException;
......@@ -34,7 +35,7 @@ import org.kohsuke.args4j.Argument;
/**
* @author ogondza
* @since XXX
* @since 1.526
*/
@Extension
public class GetNodeCommand extends CLICommand {
......@@ -51,7 +52,7 @@ public class GetNodeCommand extends CLICommand {
@Override
protected int run() throws IOException {
node.checkPermission(Jenkins.ADMINISTER);
node.checkPermission(Computer.EXTENDED_READ);
Jenkins.XSTREAM2.toXMLUTF8(node, stdout);
......
......@@ -35,7 +35,7 @@ import org.kohsuke.args4j.Argument;
/**
* @author ogondza
* @since XXX
* @since 1.526
*/
@Extension
public class UpdateNodeCommand extends CLICommand {
......
......@@ -38,7 +38,7 @@ import org.kohsuke.args4j.spi.Setter;
* Refers to {@link Node} by its name.
*
* @author ogondza
* @since XXX
* @since 1.526
*/
@MetaInfServices
public class NodeOptionHandler extends OptionHandler<Node> {
......
......@@ -1199,9 +1199,10 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
@WebMethod(name = "config.xml")
public void doConfigDotXml(StaplerRequest req, StaplerResponse rsp)
throws IOException, ServletException {
checkPermission(Jenkins.ADMINISTER);
if (req.getMethod().equals("GET")) {
// read
checkPermission(EXTENDED_READ);
rsp.setContentType("application/xml");
Jenkins.XSTREAM2.toXMLUTF8(getNode(), rsp.getOutputStream());
return;
......@@ -1238,10 +1239,10 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
/**
* Updates Job by its XML definition.
*
* @since XXX
* @since 1.526
*/
public void updateByXml(final InputStream source) throws IOException, ServletException {
checkPermission(Jenkins.ADMINISTER);
checkPermission(CONFIGURE);
Node result = (Node)Jenkins.XSTREAM2.fromXML(source);
replaceBy(result);
}
......@@ -1362,10 +1363,11 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
}
public static final PermissionGroup PERMISSIONS = new PermissionGroup(Computer.class,Messages._Computer_Permissions_Title());
public static final Permission CONFIGURE = new Permission(PERMISSIONS,"Configure", Messages._Computer_ConfigurePermission_Description(), Permission.CONFIGURE, PermissionScope.COMPUTER);
/**
* Permission to configure slaves.
* @since 1.532
*/
public static final Permission CONFIGURE = new Permission(PERMISSIONS,"Configure", Messages._Computer_ConfigurePermission_Description(), Permission.CONFIGURE, PermissionScope.COMPUTER);
public static final Permission EXTENDED_READ = new Permission(PERMISSIONS,"ExtendedRead", Messages._Computer_ExtendedReadPermission_Description(), CONFIGURE, Boolean.getBoolean("hudson.security.ExtendedReadPermission"), new PermissionScope[]{PermissionScope.COMPUTER});
public static final Permission DELETE = new Permission(PERMISSIONS,"Delete", Messages._Computer_DeletePermission_Description(), Permission.DELETE, PermissionScope.COMPUTER);
public static final Permission CREATE = new Permission(PERMISSIONS,"Create", Messages._Computer_CreatePermission_Description(), Permission.CREATE, PermissionScope.COMPUTER);
public static final Permission DISCONNECT = new Permission(PERMISSIONS,"Disconnect", Messages._Computer_DisconnectPermission_Description(), Jenkins.ADMINISTER, PermissionScope.COMPUTER);
......
......@@ -25,7 +25,6 @@
package hudson.model;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import com.thoughtworks.xstream.XStream;
import hudson.*;
import hudson.model.Descriptor.FormException;
import hudson.model.listeners.SaveableListener;
......@@ -325,7 +324,10 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
String id = null;
for (CanonicalIdResolver resolver : resolvers) {
id = resolver.resolveCanonicalId(idOrFullName, context);
if (id != null) break;
if (id != null) {
LOGGER.log(Level.FINE, "{0} mapped {1} to {2}", new Object[] {resolver, idOrFullName, id});
break;
}
}
// DefaultUserCanonicalIdResolver will always return a non-null id if all other CanonicalIdResolver failed
......@@ -342,8 +344,12 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
if (u==null && (create || getConfigFileFor(id).exists())) {
User tmp = new User(id, fullName);
User prev = byName.putIfAbsent(idkey, u = tmp);
if (prev!=null)
u = prev; // if some has already put a value in the map, use it
if (prev != null) {
u = prev; // if some has already put a value in the map, use it
if (LOGGER.isLoggable(Level.FINE) && !fullName.equals(prev.getFullName())) {
LOGGER.log(Level.FINE, "mismatch on fullName (‘" + fullName + "’ vs. ‘" + prev.getFullName() + "’) for ‘" + id + "’", new Throwable());
}
}
}
return u;
}
......@@ -710,7 +716,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
return new ContextMenu().from(this,request,response);
}
public static abstract class CanonicalIdResolver extends AbstractDescribableImpl<CanonicalIdResolver> implements Comparable<CanonicalIdResolver> {
public static abstract class CanonicalIdResolver extends AbstractDescribableImpl<CanonicalIdResolver> implements ExtensionPoint, Comparable<CanonicalIdResolver> {
/**
* context key for realm (domain) where idOrFullName has been retreived from.
......
......@@ -30,6 +30,7 @@ import hudson.Util;
import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.model.Failure;
import jenkins.model.Messages;
import hudson.util.FormValidation;
import java.io.IOException;
......@@ -132,19 +133,30 @@ public abstract class ProjectNamingStrategy implements Describable<ProjectNaming
*/
private final String namePattern;
private final String description;
private boolean forceExistingJobs;
@DataBoundConstructor
@Deprecated
public PatternProjectNamingStrategy(String namePattern, boolean forceExistingJobs) {
this(namePattern, null, forceExistingJobs);
}
/** @since 1.533 */
@DataBoundConstructor
public PatternProjectNamingStrategy(String namePattern, String description, boolean forceExistingJobs) {
this.namePattern = namePattern;
this.description = description;
this.forceExistingJobs = forceExistingJobs;
}
@Override
public void checkName(String name) throws Failure {
public void checkName(String name) {
if (StringUtils.isNotBlank(namePattern) && StringUtils.isNotBlank(name)) {
if (!Pattern.matches(namePattern, name)) {
throw new Failure(jenkins.model.Messages._Hudson_JobNameConventionNotApplyed(name, namePattern).toString());
throw new Failure(StringUtils.isEmpty(description) ?
Messages.Hudson_JobNameConventionNotApplyed(name, namePattern) :
description);
}
}
}
......@@ -153,6 +165,11 @@ public abstract class ProjectNamingStrategy implements Describable<ProjectNaming
return namePattern;
}
/** @since 1.533 */
public String getDescription() {
return description;
}
public boolean isForceExistingJobs() {
return forceExistingJobs;
}
......
......@@ -102,6 +102,7 @@ CLI.wait-node-offline.shortDescription=Wait for a node to become offline
Computer.Caption=Slave {0}
Computer.NoSuchSlaveExists=No such slave "{0}" exists. Did you mean "{1}"?
Computer.Permissions.Title=Slave
Computer.ExtendedReadPermission.Description=This permission allows users to read slave configuration.
Computer.ConfigurePermission.Description=This permission allows users to configure slaves.
Computer.DeletePermission.Description=This permission allows users to delete existing slaves.
Computer.CreatePermission.Description=This permission allows users to create slaves.
......
......@@ -6,6 +6,11 @@ def f=namespace(lib.FormTagLib)
f.entry(title:_("namePattern"), field:"namePattern") {
f.textbox(value:h.defaulted(instance?.namePattern, descriptor.DEFAULT_PATTERN),class:"fixed-width")
}
f.entry(title:_("description"), field:"description") {
f.textbox()
}
f.entry(title:_("forceExistingJobs"), field:"forceExistingJobs") {
f.checkbox(name:"forceExistingJobs")
}
......
......@@ -21,6 +21,7 @@
# THE SOFTWARE.
namePattern = Name Pattern
description = Description
forceExistingJobs = force existing
<p>
Provide a human-readable description to explain naming constraints.
Will be used as error message when job name does not match pattern
</p>
\ No newline at end of file
jenkins (1.531) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
-- Kohsuke Kawaguchi <kk@kohsuke.org> Mon, 16 Sep 2013 20:29:07 -0700
jenkins (1.530) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
</parent>
<artifactId>maven-plugin</artifactId>
......
......@@ -11,7 +11,7 @@
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<name>Jenkins plugin POM</name>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<packaging>pom</packaging>
<!--
......@@ -38,7 +38,7 @@
<dependency><!-- if a plugin wants to depend on the maven plugin, choose the right version automatically -->
<groupId>org.jenkins-ci.main</groupId>
<artifactId>maven-plugin</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
......@@ -48,25 +48,25 @@
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-war</artifactId>
<type>war</type>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-core</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>ui-samples-plugin</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<!--
......
......@@ -33,7 +33,7 @@ THE SOFTWARE.
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Jenkins main module</name>
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<artifactId>pom</artifactId>
<groupId>org.jenkins-ci.main</groupId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
</parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
......
......@@ -107,6 +107,7 @@ public class CLICommandInvoker {
GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy();
for(Permission p: permissions) {
p.setEnabled(true);
auth.add(p, username);
}
rule.jenkins.setAuthorizationStrategy(auth);
......
......@@ -23,7 +23,11 @@
*/
package hudson.model
import org.jvnet.hudson.test.HudsonTestCase
import org.jvnet.hudson.test.JenkinsRule
import org.junit.Rule
import org.junit.Test
import static org.junit.Assert.*
import org.junit.Assume
import hudson.model.UpdateCenter.DownloadJob.Success
import hudson.model.UpdateSite
......@@ -32,22 +36,26 @@ import hudson.model.UpdateSite
*
* @author Kohsuke Kawaguchi
*/
public class UpdateCenter2Test extends HudsonTestCase {
public class UpdateCenter2Test {
@Rule public JenkinsRule j = new JenkinsRule();
/**
* Makes sure a plugin installs fine.
*/
void testInstall() {
@Test void install() {
Assume.assumeFalse("SocketTimeoutException from goTo due to GET http://localhost:…/update-center.json?…", "https://jenkins.ci.cloudbees.com/job/core/job/jenkins_main_trunk/".equals(System.getenv("JOB_URL")))
UpdateSite.neverUpdate = false;
createWebClient().goTo("/") // load the metadata
def job = jenkins.updateCenter.getPlugin("changelog-history").deploy().get(); // this seems like one of the smallest plugin
j.createWebClient().goTo("") // load the metadata
def job = j.jenkins.updateCenter.getPlugin("changelog-history").deploy().get(); // this seems like one of the smallest plugin
println job.status;
assertTrue(job.status instanceof Success)
}
void testGetLastUpdatedString() {
@Test void getLastUpdatedString() {
UpdateSite.neverUpdate = false
assertTrue(jenkins.updateCenter.getById("default").due)
assertEquals(hudson.model.Messages.UpdateCenter_n_a(), jenkins.updateCenter.lastUpdatedString)
assertTrue(j.jenkins.updateCenter.getById("default").due)
assertEquals(hudson.model.Messages.UpdateCenter_n_a(), j.jenkins.updateCenter.lastUpdatedString)
}
}
......@@ -29,9 +29,9 @@ import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.text.IsEmptyString.isEmptyString;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.model.Slave;
import hudson.security.Permission;
import jenkins.model.Jenkins;
import org.junit.Before;
......@@ -50,15 +50,15 @@ public class CreateNodeCommandTest {
command = new CLICommandInvoker(j, new CreateNodeCommand());
}
@Test public void createNodeShouldFailWithoutAdministerPermision() throws Exception {
@Test public void createNodeShouldFailWithoutComputerCreatePermission() throws Exception {
final CLICommandInvoker.Result result = command
.authorizedTo(Permission.READ)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invoke()
;
assertThat(result.stderr(), containsString("user is missing the Overall/Administer permission"));
assertThat(result.stderr(), containsString("user is missing the Slave/Create permission"));
assertThat("No output expected", result.stdout(), isEmptyString());
assertThat("Command is expected to fail", result.returnCode(), equalTo(-1));
}
......@@ -66,8 +66,8 @@ public class CreateNodeCommandTest {
@Test public void createNode() throws Exception {
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Computer.CREATE, Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invoke()
;
......@@ -83,8 +83,8 @@ public class CreateNodeCommandTest {
@Test public void createNodeSpecifyingNameExplicitly() throws Exception {
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Computer.CREATE, Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invokeWithArgs("CustomSlaveName")
;
......@@ -104,8 +104,8 @@ public class CreateNodeCommandTest {
final Node originalSlave = j.createSlave("SlaveFromXml", null, null);
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Computer.CREATE, Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invokeWithArgs("CustomSlaveName")
;
......@@ -125,8 +125,8 @@ public class CreateNodeCommandTest {
j.createSlave("SlaveFromXML", null, null);
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Computer.CREATE, Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invoke()
;
......@@ -140,8 +140,8 @@ public class CreateNodeCommandTest {
j.createSlave("ExistingSlave", null, null);
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Computer.CREATE, Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invokeWithArgs("ExistingSlave")
;
......
......@@ -29,7 +29,7 @@ import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.text.IsEmptyString.isEmptyString;
import hudson.security.Permission;
import hudson.model.Computer;
import jenkins.model.Jenkins;
import org.junit.Before;
......@@ -48,16 +48,16 @@ public class GetNodeCommandTest {
command = new CLICommandInvoker(j, new GetNodeCommand());
}
@Test public void getNodeShouldFailWithoutAdministerPermision() throws Exception {
@Test public void getNodeShouldFailWithoutComputerReadPermission() throws Exception {
j.createSlave("MySlave", null, null);
final CLICommandInvoker.Result result = command
.authorizedTo(Permission.READ)
.authorizedTo(Jenkins.READ)
.invokeWithArgs("MySlave")
;
assertThat(result.stderr(), containsString("user is missing the Overall/Administer permission"));
assertThat(result.stderr(), containsString("user is missing the Slave/ExtendedRead permission"));
assertThat("No output expected", result.stdout(), isEmptyString());
assertThat("Command is expected to fail", result.returnCode(), equalTo(-1));
}
......@@ -67,7 +67,7 @@ public class GetNodeCommandTest {
j.createSlave("MySlave", null, null);
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.authorizedTo(Computer.EXTENDED_READ, Jenkins.READ)
.invokeWithArgs("MySlave")
;
......@@ -80,7 +80,7 @@ public class GetNodeCommandTest {
@Test public void getNodeShouldFailIfNodeDoesNotExist() throws Exception {
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.authorizedTo(Computer.EXTENDED_READ, Jenkins.READ)
.invokeWithArgs("MySlave")
;
......
......@@ -29,8 +29,8 @@ import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.text.IsEmptyString.isEmptyString;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.security.Permission;
import jenkins.model.Jenkins;
import org.junit.Before;
......@@ -49,16 +49,16 @@ public class UpdateNodeCommandTest {
command = new CLICommandInvoker(j, new UpdateNodeCommand());
}
@Test public void updateNodeShouldFailWithoutAdministerPermision() throws Exception {
@Test public void updateNodeShouldFailWithoutComputerConfigurePermission() throws Exception {
j.createSlave("MySlave", null, null);
final CLICommandInvoker.Result result = command
.authorizedTo(Permission.READ)
.authorizedTo(Jenkins.READ)
.invokeWithArgs("MySlave")
;
assertThat(result.stderr(), containsString("user is missing the Overall/Administer permission"));
assertThat(result.stderr(), containsString("user is missing the Slave/Configure permission"));
assertThat("No output expected", result.stdout(), isEmptyString());
assertThat("Command is expected to fail", result.returnCode(), equalTo(-1));
}
......@@ -68,8 +68,8 @@ public class UpdateNodeCommandTest {
j.createSlave("MySlave", null, null);
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Computer.CONFIGURE, Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invokeWithArgs("MySlave")
;
......@@ -86,8 +86,8 @@ public class UpdateNodeCommandTest {
@Test public void updateNodeShouldFailIfNodeDoesNotExist() throws Exception {
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.ADMINISTER)
.withStdin(getClass().getResourceAsStream("node.xml"))
.authorizedTo(Computer.CONFIGURE, Jenkins.READ)
.withStdin(Computer.class.getResourceAsStream("node.xml"))
.invokeWithArgs("MySlave")
;
......
/*
* The MIT License
*
* Copyright (c) 2013 Red Hat, 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 static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.startsWith;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import hudson.security.ACL;
import hudson.security.AccessDeniedException2;
import hudson.security.GlobalMatrixAuthorizationStrategy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/**
* @author ogondza
*/
public class ComputerConfigDotXmlTest {
@Rule public final JenkinsRule rule = new JenkinsRule();
@Mock private StaplerRequest req;
@Mock private StaplerResponse rsp;
private Computer computer;
private SecurityContext oldSecurityContext;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
computer = spy(rule.createSlave().toComputer());
oldSecurityContext = ACL.impersonate(User.get("user").impersonate());
}
@After
public void tearDown() {
SecurityContextHolder.setContext(oldSecurityContext);
}
@Test(expected = AccessDeniedException2.class)
public void configXmlGetShouldFailForUnauthorized() throws Exception {
when(req.getMethod()).thenReturn("GET");
rule.jenkins.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy());
computer.doConfigDotXml(req, rsp);
}
@Test(expected = AccessDeniedException2.class)
public void configXmlPostShouldFailForUnauthorized() throws Exception {
when(req.getMethod()).thenReturn("POST");
rule.jenkins.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy());
computer.doConfigDotXml(req, rsp);
}
@Test
public void configXmlGetShouldYieldNodeConfiguration() throws Exception {
when(req.getMethod()).thenReturn("GET");
GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy();
rule.jenkins.setAuthorizationStrategy(auth);
Computer.EXTENDED_READ.setEnabled(true);
auth.add(Computer.EXTENDED_READ, "user");
final OutputStream outputStream = captureOutput();
computer.doConfigDotXml(req, rsp);
final String out = outputStream.toString();
assertThat(out, startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
assertThat(out, containsString("<name>slave0</name>"));
assertThat(out, containsString("<description>dummy</description>"));
}
@Test
public void configXmlPostShouldUpdateNodeConfiguration() throws Exception {
when(req.getMethod()).thenReturn("POST");
GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy();
rule.jenkins.setAuthorizationStrategy(auth);
auth.add(Computer.CONFIGURE, "user");
when(req.getInputStream()).thenReturn(xmlNode("node.xml"));
computer.doConfigDotXml(req, rsp);
final Node updatedSlave = rule.jenkins.getNode("SlaveFromXML");
assertThat(updatedSlave.getNodeName(), equalTo("SlaveFromXML"));
assertThat(updatedSlave.getNumExecutors(), equalTo(42));
}
private OutputStream captureOutput() throws IOException {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
when(rsp.getOutputStream()).thenReturn(new ServletOutputStream() {
@Override
public void write(int b) throws IOException {
baos.write(b);
}
});
return baos;
}
private ServletInputStream xmlNode(final String name) {
class Stream extends ServletInputStream {
private final InputStream inner;
public Stream(final InputStream inner) {
this.inner = inner;
}
@Override
public int read() throws IOException {
return inner.read();
}
}
return new Stream(Computer.class.getResourceAsStream(name));
}
}
......@@ -47,6 +47,7 @@ import java.util.List;
import static org.junit.Assert.*;
import hudson.util.StreamTaskListener;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
......@@ -286,6 +287,7 @@ public class FingerprinterTest {
@Bug(18417)
@Test
public void fingerprintCleanup() throws Exception {
Assume.assumeFalse("for p3.upstreamProjects expected:<[hudson.model.FreeStyleProject@590e5b8[test0]]> but was:<[]>", "https://jenkins.ci.cloudbees.com/job/core/job/jenkins_main_trunk/".equals(System.getenv("JOB_URL")));
// file names shouldn't matter
FreeStyleProject p1 = createFreeStyleProjectWithFingerprints(singleContents, singleFiles);
FreeStyleProject p2 = createFreeStyleProjectWithFingerprints(singleContents, singleFiles2);
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
</parent>
<artifactId>ui-samples-plugin</artifactId>
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.532-SNAPSHOT</version>
<version>1.533-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册