Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'master' into JENKINS-29705
  • Loading branch information
jglick committed Nov 25, 2015
2 parents f790735 + 8dd67dd commit 707beee
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -5,6 +5,7 @@ Only noting significant user changes, not internal code cleanups and minor bug f
## 1.12 (upcoming)

* [JENKINS-29705](https://issues.jenkins-ci.org/browse/JENKINS-29705): added _Thread Dump_ link to running flow builds for diagnosing problems like hangs.
* [JENKINS-31649](https://issues.jenkins-ci.org/browse/JENKINS-31649): correctly display pending queue items for blocked `node {}` tasks when on Jenkins 1.639+ (will not appear in 1.638 or 1.625.2).
* [JENKINS-31691](https://issues.jenkins-ci.org/browse/JENKINS-31691): added `isUnix` step.
* [JENKINS-31585](https://issues.jenkins-ci.org/browse/JENKINS-31585): make new script editor resizable.

Expand Down
Expand Up @@ -26,9 +26,13 @@

import hudson.model.Computer;
import hudson.model.Node;
import hudson.model.Queue;
import hudson.model.User;
import hudson.model.labels.LabelAtom;
import hudson.remoting.Launcher;
import hudson.remoting.Which;
import hudson.security.ACL;
import hudson.security.GlobalMatrixAuthorizationStrategy;
import hudson.slaves.DumbSlave;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.JNLPLauncher;
Expand All @@ -46,6 +50,7 @@
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import org.apache.tools.ant.util.JavaEnvUtils;
import org.jenkinsci.plugins.workflow.SingleJobTestBase;
import org.jenkinsci.plugins.workflow.actions.WorkspaceAction;
Expand Down Expand Up @@ -378,4 +383,36 @@ private void startJnlpProc() throws Exception {
});
}

@Issue("JENKINS-31649")
@Test public void queueTaskVisibility() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
jenkins().setSecurityRealm(story.j.createDummySecurityRealm());
GlobalMatrixAuthorizationStrategy gmas = new GlobalMatrixAuthorizationStrategy();
gmas.add(Jenkins.ADMINISTER, "admin");
jenkins().setAuthorizationStrategy(gmas);
p = jenkins().createProject(WorkflowJob.class, "demo");
p.setDefinition(new CpsFlowDefinition("node('nonexistent') {}", true));
startBuilding();
story.j.waitForMessage("Still waiting to schedule task", b);
ACL.impersonate(User.get("admin").impersonate(), new Runnable() {
@Override public void run() {
Queue.Item[] items = Queue.getInstance().getItems();
assertEquals(1, items.length); // fails in 1.638
assertEquals(p, items[0].task.getOwnerTask());
}
});
/* TODO uncomment when on 1.639+, or 1.625.3 if JENKINS-31649 is backported:
ACL.impersonate(User.get("devel").impersonate(), new Runnable() {
@Override public void run() {
Queue.Item[] items = Queue.getInstance().getItems();
assertEquals(0, items.length); // fails in 1.609.2
}
});
*/
// TODO this would be a good time to add a third user with READ but no CANCEL permission and check behavior
}
});
}

}
Expand Up @@ -22,6 +22,7 @@
import hudson.remoting.RequestAbortedException;
import hudson.security.ACL;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import hudson.slaves.WorkspaceList;
import java.io.IOException;
import java.io.PrintStream;
Expand All @@ -33,16 +34,20 @@
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import static java.util.logging.Level.*;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import jenkins.model.Jenkins;
import jenkins.model.Jenkins.MasterComputer;
import jenkins.model.queue.AsynchronousExecution;
import jenkins.util.Timer;
import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.Authentication;
import org.jenkinsci.plugins.durabletask.executors.ContinuableExecutable;
import org.jenkinsci.plugins.durabletask.executors.ContinuedTask;
import org.jenkinsci.plugins.workflow.flow.FlowExecution;
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.steps.AbstractStepExecutionImpl;
import org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback;
Expand All @@ -53,10 +58,6 @@
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.accmod.restrictions.NoExternalUse;

import static java.util.logging.Level.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ExecutorStepExecution extends AbstractStepExecutionImpl {

@Inject(optional=true) private transient ExecutorStep step;
Expand Down Expand Up @@ -142,7 +143,7 @@ private static final class RunningTask {

private static final String COOKIE_VAR = "JENKINS_SERVER_COOKIE";

public static final class PlaceholderTask implements ContinuedTask, Serializable {
public static final class PlaceholderTask implements ContinuedTask, Serializable, AccessControlled {

/** keys are {@link #cookie}s */
private static final Map<String,RunningTask> runningTasks = new HashMap<String,RunningTask>();
Expand Down Expand Up @@ -237,41 +238,49 @@ private Object readResolve() {
}

/**
* Something we can use to check abort permission.
* Something we can use to check abort and read permissions.
* Normally this will be a {@link Run}.
* However if things are badly broken, for example if the build has been deleted,
* then as a fallback we use the Jenkins root.
* This allows an administrator to clean up dead queue items and executor cells.
* TODO make {@link FlowExecutionOwner} implement {@link AccessControlled}
* so that an implementation could fall back to checking {@link Job} permission.
*/
private @Nonnull AccessControlled accessControlled() {
@Override public ACL getACL() {
try {
if (!context.isReady()) {
return Jenkins.getActiveInstance();
return Jenkins.getActiveInstance().getACL();
}
FlowExecution exec = context.get(FlowExecution.class);
if (exec == null) {
return Jenkins.getActiveInstance();
return Jenkins.getActiveInstance().getACL();
}
Queue.Executable executable = exec.getOwner().getExecutable();
if (executable instanceof AccessControlled) {
return (AccessControlled) executable;
return ((AccessControlled) executable).getACL();
} else {
return Jenkins.getActiveInstance();
return Jenkins.getActiveInstance().getACL();
}
} catch (Exception x) {
LOGGER.log(FINE, null, x);
return Jenkins.getActiveInstance();
return Jenkins.getActiveInstance().getACL();
}
}

@Override public void checkPermission(Permission p) throws AccessDeniedException {
getACL().checkPermission(p);
}

@Override public boolean hasPermission(Permission p) {
return getACL().hasPermission(p);
}

@Override public void checkAbortPermission() {
accessControlled().checkPermission(Item.CANCEL);
checkPermission(Item.CANCEL);
}

@Override public boolean hasAbortPermission() {
return accessControlled().hasPermission(Item.CANCEL);
return hasPermission(Item.CANCEL);
}

public @CheckForNull Run<?,?> run() {
Expand Down

0 comments on commit 707beee

Please sign in to comment.