Skip to content

Commit 99e78df

Browse files
authored
Merge pull request #1155 from patbos/cloud_check
2 parents 6a27e08 + 4ee1053 commit 99e78df

File tree

4 files changed

+197
-1
lines changed

4 files changed

+197
-1
lines changed

src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFolderProperty.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.stream.Collectors;
1111

1212
import edu.umd.cs.findbugs.annotations.NonNull;
13+
import hudson.model.Job;
1314
import org.apache.commons.lang.StringUtils;
1415
import org.kohsuke.accmod.Restricted;
1516
import org.kohsuke.accmod.restrictions.DoNotUse;
@@ -99,6 +100,19 @@ private static List<UsagePermission> buildPermissions() {
99100
return ps;
100101
}
101102

103+
@SuppressWarnings({"rawtypes"})
104+
public static boolean isAllowed(KubernetesSlave agent, Job job) {
105+
ItemGroup parent = job.getParent();
106+
Set<String> allowedClouds = new HashSet<>();
107+
108+
KubernetesCloud targetCloud = agent.getKubernetesCloud();
109+
if (targetCloud.isUsageRestricted()) {
110+
KubernetesFolderProperty.collectAllowedClouds(allowedClouds, parent);
111+
return allowedClouds.contains(targetCloud.name);
112+
}
113+
return true;
114+
}
115+
102116
private static String PREFIX_USAGE_PERMISSION = "usage-permission-";
103117

104118
@Override
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.csanchez.jenkins.plugins.kubernetes;
2+
3+
import hudson.Extension;
4+
import hudson.model.Job;
5+
import hudson.model.Node;
6+
import hudson.model.Queue;
7+
import hudson.model.Queue.Task;
8+
9+
import hudson.model.queue.CauseOfBlockage;
10+
import hudson.model.queue.QueueTaskDispatcher;
11+
12+
@Extension
13+
@SuppressWarnings({"rawtypes"})
14+
public class KubernetesQueueTaskDispatcher extends QueueTaskDispatcher {
15+
16+
@Override
17+
public CauseOfBlockage canTake(Node node, Queue.BuildableItem item) {
18+
if (node instanceof KubernetesSlave) {
19+
KubernetesSlave slave = (KubernetesSlave) node;
20+
Task ownerTask = item.task.getOwnerTask();
21+
if (!KubernetesFolderProperty.isAllowed(slave, (Job) ownerTask)) {
22+
return new KubernetesCloudNotAllowed(slave.getKubernetesCloud(), (Job) ownerTask);
23+
}
24+
}
25+
return null;
26+
}
27+
28+
public static final class KubernetesCloudNotAllowed extends CauseOfBlockage {
29+
30+
private final KubernetesCloud cloud;
31+
private final Job job;
32+
33+
public KubernetesCloudNotAllowed(KubernetesCloud cloud, Job job) {
34+
this.cloud = cloud;
35+
this.job = job;
36+
}
37+
38+
@Override
39+
public String getShortDescription() {
40+
return Messages.KubernetesCloudNotAllowed_Description(cloud.name, job.getFullName());
41+
}
42+
}
43+
}

src/main/resources/org/csanchez/jenkins/plugins/kubernetes/Messages.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ KubernetesFolderProperty.displayName=Kubernetes
77
KubernetesSlave.HomeWarning=[WARNING] HOME is set to / in the jnlp container. You may encounter \
88
troubles when using tools or ssh client. This usually happens if the uid doesn't have any \
99
entry in /etc/passwd. Please add a user to your Dockerfile or set the HOME environment \
10-
variable to a valid directory in the pod template definition.
10+
variable to a valid directory in the pod template definition.
11+
KubernetesCloudNotAllowed.Description=Kubernetes cloud {0} is not allowed for folder containing job {1}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package org.csanchez.jenkins.plugins.kubernetes;
2+
3+
import com.cloudbees.hudson.plugins.folder.Folder;
4+
import hudson.model.FreeStyleProject;
5+
import hudson.model.Project;
6+
import hudson.model.Queue;
7+
import hudson.model.Slave;
8+
import hudson.model.queue.CauseOfBlockage;
9+
import hudson.slaves.DumbSlave;
10+
import hudson.slaves.RetentionStrategy;
11+
import net.sf.json.JSONObject;
12+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
13+
import org.jenkinsci.plugins.workflow.support.steps.ExecutorStepExecution;
14+
import org.junit.Rule;
15+
import org.junit.Test;
16+
import org.jvnet.hudson.test.JenkinsRule;
17+
import org.mockito.Mock;
18+
import org.mockito.junit.MockitoJUnit;
19+
import org.mockito.junit.MockitoRule;
20+
21+
import java.util.ArrayList;
22+
import java.util.Calendar;
23+
24+
import static org.junit.Assert.*;
25+
import static org.mockito.Mockito.when;
26+
27+
public class KubernetesQueueTaskDispatcherTest {
28+
29+
@Rule
30+
public JenkinsRule jenkins = new JenkinsRule();
31+
32+
@Rule
33+
public MockitoRule mockitoRule = MockitoJUnit.rule();
34+
35+
@Mock
36+
private ExecutorStepExecution.PlaceholderTask task;
37+
38+
private Folder folderA;
39+
private Folder folderB;
40+
private KubernetesSlave slaveA;
41+
private KubernetesSlave slaveB;
42+
43+
public void setUpTwoClouds() throws Exception {
44+
folderA = new Folder(jenkins.jenkins, "A");
45+
folderB = new Folder(jenkins.jenkins, "B");
46+
jenkins.jenkins.add(folderA, "Folder A");
47+
jenkins.jenkins.add(folderB, "Folder B");
48+
49+
KubernetesCloud cloudA = new KubernetesCloud("A");
50+
cloudA.setUsageRestricted(true);
51+
52+
KubernetesCloud cloudB = new KubernetesCloud("B");
53+
cloudB.setUsageRestricted(true);
54+
55+
jenkins.jenkins.clouds.add(cloudA);
56+
jenkins.jenkins.clouds.add(cloudB);
57+
58+
KubernetesFolderProperty property1 = new KubernetesFolderProperty();
59+
folderA.addProperty(property1);
60+
JSONObject json1 = new JSONObject();
61+
json1.element("usage-permission-A", true);
62+
json1.element("usage-permission-B", false);
63+
folderA.addProperty(property1.reconfigure(null, json1));
64+
65+
KubernetesFolderProperty property2 = new KubernetesFolderProperty();
66+
folderB.addProperty(property2);
67+
JSONObject json2 = new JSONObject();
68+
json2.element("usage-permission-A", false);
69+
json2.element("usage-permission-B", true);
70+
folderB.addProperty(property2.reconfigure(null, json2));
71+
72+
slaveA = new KubernetesSlave("A", new PodTemplate(), "testA", "A", "dockerA", new KubernetesLauncher(), RetentionStrategy.INSTANCE);
73+
slaveB = new KubernetesSlave("B", new PodTemplate(), "testB", "B", "dockerB", new KubernetesLauncher(), RetentionStrategy.INSTANCE);
74+
}
75+
76+
77+
@Test
78+
public void checkRestrictedTwoClouds() throws Exception {
79+
setUpTwoClouds();
80+
81+
FreeStyleProject projectA = folderA.createProject(FreeStyleProject.class, "buildJob");
82+
FreeStyleProject projectB = folderB.createProject(FreeStyleProject.class, "buildJob");
83+
KubernetesQueueTaskDispatcher dispatcher = new KubernetesQueueTaskDispatcher();
84+
85+
assertNull(dispatcher.canTake(slaveA, new Queue.BuildableItem(new Queue.WaitingItem(Calendar.getInstance(),
86+
projectA, new ArrayList<>()))));
87+
assertTrue(canTake(dispatcher, slaveB, projectA) instanceof KubernetesQueueTaskDispatcher.KubernetesCloudNotAllowed);
88+
assertTrue(canTake(dispatcher, slaveA, projectB) instanceof KubernetesQueueTaskDispatcher.KubernetesCloudNotAllowed);
89+
assertNull(canTake(dispatcher, slaveB, projectB));
90+
}
91+
92+
@Test
93+
public void checkNotRestrictedClouds() throws Exception {
94+
Folder folder = new Folder(jenkins.jenkins, "C");
95+
FreeStyleProject project = folder.createProject(FreeStyleProject.class, "buildJob");
96+
jenkins.jenkins.add(folder, "C");
97+
KubernetesCloud cloud = new KubernetesCloud("C");
98+
cloud.setUsageRestricted(false);
99+
jenkins.jenkins.clouds.add(cloud);
100+
KubernetesQueueTaskDispatcher dispatcher = new KubernetesQueueTaskDispatcher();
101+
KubernetesSlave slave = new KubernetesSlave("C", new PodTemplate(), "testC", "C", "dockerC", new KubernetesLauncher(), RetentionStrategy.INSTANCE);
102+
103+
assertNull(canTake(dispatcher, slave, project));
104+
}
105+
106+
107+
@Test
108+
public void checkDumbSlave() throws Exception {
109+
DumbSlave slave = jenkins.createOnlineSlave();
110+
FreeStyleProject project = jenkins.createProject(FreeStyleProject.class);
111+
KubernetesQueueTaskDispatcher dispatcher = new KubernetesQueueTaskDispatcher();
112+
113+
assertNull(canTake(dispatcher, slave, project));
114+
}
115+
116+
@Test
117+
public void checkPipelinesRestrictedTwoClouds() throws Exception {
118+
setUpTwoClouds();
119+
120+
WorkflowJob job = folderA.createProject(WorkflowJob.class, "pipeline");
121+
when(task.getOwnerTask()).thenReturn(job);
122+
KubernetesQueueTaskDispatcher dispatcher = new KubernetesQueueTaskDispatcher();
123+
124+
assertNull(canTake(dispatcher, slaveA, task));
125+
assertTrue(canTake(dispatcher, slaveB, task) instanceof KubernetesQueueTaskDispatcher.KubernetesCloudNotAllowed);
126+
}
127+
128+
private CauseOfBlockage canTake(KubernetesQueueTaskDispatcher dispatcher, Slave slave, Project project) {
129+
return dispatcher.canTake(slave, new Queue.BuildableItem(new Queue.WaitingItem(Calendar.getInstance(),
130+
project, new ArrayList<>())));
131+
}
132+
133+
private CauseOfBlockage canTake(KubernetesQueueTaskDispatcher dispatcher, Slave slave, Queue.Task task) {
134+
return dispatcher.canTake(slave, new Queue.BuildableItem(new Queue.WaitingItem(Calendar.getInstance(),
135+
task, new ArrayList<>())));
136+
}
137+
138+
}

0 commit comments

Comments
 (0)