下面列出了怎么用hudson.model.Label的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public Collection<PlannedNode> provision(Label label, int excessWorkload) {
Set<String> allInProvisioning = getNodesInProvisioning(label);
LOGGER.info("In provisioning : " + allInProvisioning);
int toBeProvisioned = Math.max(0, excessWorkload - allInProvisioning.size());
LOGGER.info("Excess workload after pending Kubernetes agents: " + toBeProvisioned);
List<PlannedNode> provisionNodes = new ArrayList<>();
for (int i = 0; i < toBeProvisioned; i++) {
PlannedNode node = new PlannedNode(name,
Computer.threadPoolForRemoting.submit(() -> new KafkaCloudSlave(this)),
AGENT_NUM_EXECUTORS);
provisionNodes.add(node);
}
return provisionNodes;
}
@DataBoundConstructor
public NomadSlaveTemplate(
String cpu,
String memory,
String disk,
String labels,
String remoteFs,
String idleTerminationInMinutes,
String region,
String priority,
String image
) {
this.cpu = Integer.parseInt(cpu);
this.memory = Integer.parseInt(memory);
this.disk = Integer.parseInt(disk);
this.priority = Integer.parseInt(priority);
this.idleTerminationInMinutes = Integer.parseInt(idleTerminationInMinutes);
this.remoteFs = remoteFs;
this.labels = Util.fixNull(labels);
this.labelSet = Label.parse(labels);
this.region = region;
this.image = image;
readResolve();
}
protected void should_connect_agent(DockerTemplate template) throws IOException, ExecutionException, InterruptedException, TimeoutException {
// FIXME on CI windows nodes don't have Docker4Windows
Assume.assumeFalse(SystemUtils.IS_OS_WINDOWS);
String dockerHost = SystemUtils.IS_OS_WINDOWS ? "tcp://localhost:2375" : "unix:///var/run/docker.sock";
DockerCloud cloud = new DockerCloud(cloudName, new DockerAPI(new DockerServerEndpoint(dockerHost, null)),
Collections.singletonList(template));
j.jenkins.clouds.replaceBy(Collections.singleton(cloud));
final FreeStyleProject project = j.createFreeStyleProject("test-docker-ssh");
project.setAssignedLabel(Label.get(LABEL));
project.getBuildersList().add(new Shell("whoami"));
final QueueTaskFuture<FreeStyleBuild> scheduledBuild = project.scheduleBuild2(0);
try {
final FreeStyleBuild build = scheduledBuild.get(60L, TimeUnit.SECONDS);
Assert.assertTrue(build.getResult() == Result.SUCCESS);
Assert.assertTrue(build.getLog().contains("jenkins"));
} finally {
scheduledBuild.cancel(true);
}
}
@Test
public void givenEC2CloudsWhenOneCanCoverCapacity_shouldDoScalingForFirstOnly() {
when(snapshot.getQueueLength()).thenReturn(2);
when(state.getLabel()).thenReturn(label);
final EC2FleetCloud ec2FleetCloud1 = mock(EC2FleetCloud.class);
clouds.add(ec2FleetCloud1);
final EC2FleetCloud ec2FleetCloud2 = mock(EC2FleetCloud.class);
clouds.add(ec2FleetCloud2);
when(ec2FleetCloud1.canProvision(any(Label.class))).thenReturn(true);
when(ec2FleetCloud2.canProvision(any(Label.class))).thenReturn(true);
when(ec2FleetCloud1.isNoDelayProvision()).thenReturn(true);
when(ec2FleetCloud2.isNoDelayProvision()).thenReturn(true);
when(ec2FleetCloud1.provision(any(Label.class), anyInt())).thenReturn(Arrays.asList(
mock(NodeProvisioner.PlannedNode.class),
mock(NodeProvisioner.PlannedNode.class)
));
Assert.assertEquals(
NodeProvisioner.StrategyDecision.PROVISIONING_COMPLETED,
strategy.apply(state));
verify(ec2FleetCloud1, times(1)).provision(label, 2);
verify(ec2FleetCloud2, never()).provision(any(Label.class), anyInt());
}
@Test
public void should_not_keep_planned_node_if_configured_so_jenkins_will_overprovision() throws Exception {
ComputerLauncher computerLauncher = mock(ComputerLauncher.class);
ComputerConnector computerConnector = mock(ComputerConnector.class);
when(computerConnector.launch(anyString(), any(TaskListener.class))).thenReturn(computerLauncher);
final EC2FleetCloud cloud = spy(new EC2FleetCloud(null, null, "credId", null, "region",
null, "fId", "momo", null, computerConnector, false, false,
0, 0, 10, 1, false, false,
false, 0, 0, false,
10, false));
j.jenkins.clouds.add(cloud);
mockEc2ApiToDescribeInstancesWhenModified(InstanceStateName.Running);
getQueueTaskFutures(1);
tryUntil(new Runnable() {
@Override
public void run() {
j.jenkins.getLabelAtom("momo").nodeProvisioner.suggestReviewNow();
verify(cloud, atLeast(2)).provision(any(Label.class), anyInt());
}
});
}
@DataBoundConstructor
public DockerTemplate(@Nonnull DockerTemplateBase dockerTemplateBase,
@Nonnull DockerComputerConnector connector,
String labelString,
String instanceCapStr
) {
this.dockerTemplateBase = dockerTemplateBase;
this.connector = connector;
this.labelString = Util.fixEmpty(labelString);
if (Strings.isNullOrEmpty(instanceCapStr)) {
this.instanceCap = Integer.MAX_VALUE;
} else {
this.instanceCap = Integer.parseInt(instanceCapStr);
}
labelSet = Label.parse(labelString);
}
/**
* Multiple amis can have the same label.
*
* @return Templates matched to requested label assuming slave Mode
*/
public List<DockerTemplate> getTemplates(Label label) {
final List<DockerTemplate> dockerTemplates = new ArrayList<>();
for (DockerTemplate t : getTemplates()) {
if ( t.getDisabled().isDisabled() ) {
continue; // pretend it doesn't exist
}
if (label == null && t.getMode() == Node.Mode.NORMAL) {
dockerTemplates.add(t);
}
if (label != null && label.matches(t.getLabelSet())) {
dockerTemplates.add(t);
}
}
// add temporary templates matched to requested label
for (DockerTemplate template : getJobTemplates().values()) {
if (label != null && label.matches(template.getLabelSet())) {
dockerTemplates.add(template);
}
}
return dockerTemplates;
}
@Nonnull
public List<DockerCloud> getDockerClouds(Label label) {
List<DockerCloud> provisionClouds;
//create a random list of docker clouds and prioritize idle clouds
List<DockerCloud> availableClouds = getAvailableDockerClouds(label);
if (availableClouds.size() > 0) {
//select available clouds based on label which have potential capacity
LOG.debug("Picking from available clouds.");
provisionClouds = availableClouds;
} else {
//if there's no available clouds then fall back to original behavior
LOG.debug("Falling back to getting all clouds regardless of availability.");
provisionClouds = getAllDockerClouds();
}
//randomize the order of the DockerCloud list
Collections.shuffle(provisionClouds);
//sort by least loaded DockerCloud (i.e. fewest provisioned slaves)
provisionClouds.sort(new DockerCloudLoadComparator());
LOG.debug("Least loaded randomized DockerCloud: " +
((provisionClouds.size() > 0) ? provisionClouds.get(0).name : "none available"));
return provisionClouds;
}
/**
* Pass the given pod templates list into all filters implementations.
*
* @param cloud The cloud instance the pod templates are getting considered for
* @param podTemplates The initial list of pod templates
* @param label The label that was requested for provisioning
* @return The pod template list after filtering
*/
public static List<PodTemplate> applyAll(@Nonnull KubernetesCloud cloud, @Nonnull List<PodTemplate> podTemplates, @CheckForNull Label label) {
List<PodTemplate> result = new ArrayList<>();
for (PodTemplate t : podTemplates) {
PodTemplate output = t;
for (PodTemplateFilter f : all()) {
output = f.transform(cloud, output, label);
if (output == null) {
break;
}
}
if (output != null) {
result.add(output);
}
}
return result;
}
@Test
public void podTemplateWithMultipleLabels() throws Exception {
PodTemplate pt = new PodTemplate();
pt.setName("podTemplate");
pt.setLabel("label1 label2");
ContainerTemplate jnlp = new ContainerTemplate("jnlp", "jenkins/jnlp-slave:3.35-5-alpine");
pt.setContainers(Collections.singletonList(jnlp));
cloud.addTemplate(pt);
SemaphoreStep.waitForStart("pod/1", b);
Map<String, String> labels = getLabels(cloud, this, name);
labels.put("jenkins/label","label1_label2");
KubernetesSlave node = r.jenkins.getNodes().stream()
.filter(KubernetesSlave.class::isInstance)
.map(KubernetesSlave.class::cast)
.findAny().get();
assertTrue(node.getAssignedLabels().containsAll(Label.parse("label1 label2")));
PodList pods = cloud.connect().pods().withLabels(labels).list();
assertThat(
"Expected one pod with labels " + labels + " but got: "
+ pods.getItems().stream().map(pod -> pod.getMetadata()).collect(Collectors.toList()),
pods.getItems(), hasSize(1));
SemaphoreStep.success("pod/1", null);
r.assertBuildStatusSuccess(r.waitForCompletion(b));
}
@Override
public CauseOfBlockage canTake(final Queue.BuildableItem item) {
final Label l = item.getAssignedLabel();
if (l != null && this.name.equals(l.getName())) {
return null;
}
return super.canTake(item);
}
public Set<String> getNodesInProvisioning(@CheckForNull Label label) {
if (label == null) return Collections.emptySet();
return label.getNodes().stream()
.filter(KafkaCloudSlave.class::isInstance)
.filter(node -> {
Computer computer = node.toComputer();
return computer != null && !computer.isOnline();
})
.map(Node::getNodeName)
.collect(Collectors.toSet());
}
private ECSTaskTemplate getTemplate(Label label) {
if (label == null) {
return null;
}
for (ECSTaskTemplate t : getAllTemplates()) {
if (label.matches(t.getLabelSet())) {
return t;
}
}
return null;
}
@NonNull
@Override
public Set<Attribute<LabelAtom, ?>> describe() {
return new HashSet<>(Arrays.asList(
new Attribute<LabelAtom, String>("name", String.class)
.getter(Label::getName),
new MultivaluedAttribute<LabelAtom, LabelAtomProperty>("properties", LabelAtomProperty.class)
.getter(labelAtom -> labelAtom.getProperties())
.setter((labelAtom, properties) -> labelAtom.getProperties().addAll(properties))
));
}
@Test
@ConfiguredWithReadme("docker/README.md")
public void update_docker_cloud() throws Exception {
DockerCloud docker = DockerCloud.getCloudByName("docker");
assertNotNull(docker);
assertNotNull(docker.getDockerApi());
assertNotNull(docker.getDockerApi().getDockerHost());
assertEquals("unix:///var/run/docker.sock", docker.getDockerApi().getDockerHost().getUri());
DockerTemplate template = docker.getTemplate(Label.get("docker-agent"));
checkTemplate(template, "docker-agent", "jenkins", "/home/jenkins/agent", "10",
new String[] { "hello:/hello", "world:/world"}, "hello=world\nfoo=bar");
ConfigurationAsCode.get().configure(getClass().getResource("DockerCloudTest2.yml").toExternalForm());
docker = DockerCloud.getCloudByName("docker");
assertNotNull(docker);
assertNotNull(docker.getDockerApi());
assertNotNull(docker.getDockerApi().getDockerHost());
assertEquals("unix:///var/run/docker.sock", docker.getDockerApi().getDockerHost().getUri());
template = docker.getTemplate(Label.get("docker-agent"));
checkTemplate(template, "docker-agent", "jenkins", "/home/jenkins/agent", "10",
new String[] { "hello:/hello", "world:/world"}, "hello=world\nfoo=bar");
template = docker.getTemplate(Label.get("generic"));
checkTemplate(template, "generic", "jenkins", "/home/jenkins/agent2", "5",
new String[] { "hello:/hello", "world:/world"}, "hello=world\nfoo=bar");
}
public NomadSlaveTemplate getTemplate(Label label) {
for (NomadSlaveTemplate t : templates) {
if (label == null && !t.getLabelSet().isEmpty()) {
continue;
}
if ((label == null && t.getLabelSet().isEmpty()) || (label != null && label.matches(t.getLabelSet()))) {
return t;
}
}
return null;
}
@Test @Ignore
public void replayRunTest() throws Exception {
WorkflowJob job1 = j.jenkins.createProject(WorkflowJob.class, "pipeline1");
j.createOnlineSlave(Label.get("remote"));
job1.setDefinition(new CpsFlowDefinition(
"node('remote') {\n" +
" ws {\n" +
" git($/" + sampleRepo + "/$)\n" +
" }\n" +
"}"));
WorkflowRun b1 = job1.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(b1);
sampleRepo.write("file1", "");
sampleRepo.git("add", "file1");
sampleRepo.git("commit", "--message=init");
WorkflowRun b2 = job1.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(b2);
Assert.assertNotEquals(new PipelineRunImpl(b1, null, null).getCommitId(), new PipelineRunImpl(b2, null, null).getCommitId());
request().post("/organizations/jenkins/pipelines/pipeline1/runs/1/replay").build(String.class);
j.waitForCompletion(job1.getLastBuild());
Map r = request().get("/organizations/jenkins/pipelines/pipeline1/runs/3/").build(Map.class);
assertEquals(r.get("commitId"), new PipelineRunImpl(b2,null, null).getCommitId());
}
@Issue("JENKINS-44981")
@Test
public void queuedSingleNode() throws Exception {
WorkflowJob p = createWorkflowJobWithJenkinsfile(getClass(),"queuedSingleNode.jenkinsfile");
// Ensure null before first run
Map pipeline = request().get(String.format("/organizations/jenkins/pipelines/%s/", p.getName())).build(Map.class);
Assert.assertNull(pipeline.get("latestRun"));
// Run until completed
WorkflowRun r = p.scheduleBuild2(0).waitForStart();
j.waitForMessage("Still waiting to schedule task", r);
// Get latest run for this pipeline
pipeline = request().get(String.format("/organizations/jenkins/pipelines/%s/", p.getName())).build(Map.class);
Map latestRun = (Map) pipeline.get("latestRun");
Assert.assertEquals("QUEUED", latestRun.get("state"));
Assert.assertEquals("1", latestRun.get("id"));
// Jenkins 2.125 introduced quotes around these labels - see commit 91ddc6. This came
// just after the current Jenkins LTS, which is version 2.121.1. So this assert now
// tests for the new quoted version, and the old non-quoted version.
Assert.assertThat((String)latestRun.get("causeOfBlockage"), anyOf(
equalTo("\u2018Jenkins\u2019 doesn’t have label \u2018test\u2019"),
equalTo("Jenkins doesn’t have label test")
));
j.createOnlineSlave(Label.get("test"));
j.assertBuildStatusSuccess(j.waitForCompletion(r));
}
@Test
public void givenNoRequiredCapacity_shouldDoNotScale() {
final EC2FleetCloud ec2FleetCloud = mock(EC2FleetCloud.class);
clouds.add(ec2FleetCloud);
strategy.apply(state);
verify(ec2FleetCloud, never()).canProvision(any(Label.class));
}
@Test
public void givenAvailableSameAsRequiredCapacity_shouldDoNotScale() {
final EC2FleetCloud ec2FleetCloud = mock(EC2FleetCloud.class);
clouds.add(ec2FleetCloud);
when(snapshot.getQueueLength()).thenReturn(10);
when(snapshot.getAvailableExecutors()).thenReturn(10);
Assert.assertEquals(
NodeProvisioner.StrategyDecision.PROVISIONING_COMPLETED,
strategy.apply(state));
verify(ec2FleetCloud, never()).canProvision(any(Label.class));
}
@Test
public void givenEC2CloudWithDisabledNoDelay_shouldDoNotScale() {
when(snapshot.getQueueLength()).thenReturn(10);
when(state.getLabel()).thenReturn(label);
final EC2FleetCloud ec2FleetCloud = mock(EC2FleetCloud.class);
clouds.add(ec2FleetCloud);
when(ec2FleetCloud.canProvision(any(Label.class))).thenReturn(true);
when(ec2FleetCloud.isNoDelayProvision()).thenReturn(false);
Assert.assertEquals(
NodeProvisioner.StrategyDecision.CONSULT_REMAINING_STRATEGIES,
strategy.apply(state));
verify(ec2FleetCloud, never()).provision(any(Label.class), anyInt());
}
@Test
public void givenEC2CloudWhichCannotProvision_shouldDoNotScale() {
when(snapshot.getQueueLength()).thenReturn(10);
when(state.getLabel()).thenReturn(label);
final EC2FleetCloud ec2FleetCloud = mock(EC2FleetCloud.class);
clouds.add(ec2FleetCloud);
when(ec2FleetCloud.canProvision(any(Label.class))).thenReturn(false);
Assert.assertEquals(
NodeProvisioner.StrategyDecision.CONSULT_REMAINING_STRATEGIES,
strategy.apply(state));
verify(ec2FleetCloud, never()).provision(any(Label.class), anyInt());
}
@Override
public Collection<NodeProvisioner.PlannedNode> provision(
final Label label, final int excessWorkload) {
final Collection<NodeProvisioner.PlannedNode> r = super.provision(label, excessWorkload);
for (NodeProvisioner.PlannedNode ignore : r) provisionTimes.add(System.currentTimeMillis());
return r;
}
@Test
public void should_keep_planned_node_until_node_will_not_be_online_so_jenkins_will_not_request_overprovision() throws Exception {
ComputerLauncher computerLauncher = mock(ComputerLauncher.class);
ComputerConnector computerConnector = mock(ComputerConnector.class);
when(computerConnector.launch(anyString(), any(TaskListener.class))).thenReturn(computerLauncher);
EC2FleetCloud cloud = spy(new EC2FleetCloud(null, null, "credId", null, "region",
null, "fId", "momo", null, computerConnector, false, false,
0, 0, 10, 1, false, false,
false, 300, 15, false,
2, false));
// provide init state
cloud.setStats(new FleetStateStats("", 0, "active",
Collections.<String>emptySet(), Collections.<String, Double>emptyMap()));
j.jenkins.clouds.add(cloud);
mockEc2ApiToDescribeInstancesWhenModified(InstanceStateName.Running);
List<QueueTaskFuture> rs = getQueueTaskFutures(1);
final String labelString = "momo";
triggerSuggestReviewNow(labelString);
Thread.sleep(TimeUnit.MINUTES.toMillis(2));
verify(cloud, times(1)).provision(any(Label.class), anyInt());
cancelTasks(rs);
}
@Override
public Collection<NodeProvisioner.PlannedNode> provision(
final Label label, final int excessWorkload) {
try (Meter.Shot s = provisionMeter.start()) {
return super.provision(label, excessWorkload);
}
}
@SuppressWarnings("unused") // used by stapler
public ComboBoxModel doFillLabelItems() {
ComboBoxModel cbm = new ComboBoxModel();
Set<Label> labels = Jenkins.get().getLabels();
for (Label label : labels) {
cbm.add(label.getDisplayName());
}
return cbm;
}
@Test
public void testInstanceCap() {
KubernetesCloud cloud = new KubernetesCloud("name") {
@Override
public KubernetesClient connect() {
KubernetesClient mockClient = Mockito.mock(KubernetesClient.class);
Mockito.when(mockClient.getNamespace()).thenReturn("default");
MixedOperation<Pod, PodList, DoneablePod, PodResource<Pod, DoneablePod>> operation = Mockito.mock(MixedOperation.class);
Mockito.when(operation.inNamespace(Mockito.anyString())).thenReturn(operation);
Mockito.when(operation.withLabels(Mockito.anyMap())).thenReturn(operation);
PodList podList = Mockito.mock(PodList.class);
Mockito.when(podList.getItems()).thenReturn(new ArrayList<>());
Mockito.when(operation.list()).thenReturn(podList);
Mockito.when(mockClient.pods()).thenReturn(operation);
return mockClient;
}
};
PodTemplate podTemplate = new PodTemplate();
podTemplate.setName("test");
podTemplate.setLabel("test");
cloud.addTemplate(podTemplate);
Label test = Label.get("test");
assertTrue(cloud.canProvision(test));
Collection<NodeProvisioner.PlannedNode> plannedNodes = cloud.provision(test, 200);
assertEquals(200, plannedNodes.size());
podTemplate.setInstanceCap(5);
plannedNodes = cloud.provision(test, 200);
assertEquals(5, plannedNodes.size());
}
@Override
public synchronized Collection<NodeProvisioner.PlannedNode> provision(Label label, int excessWorkload) {
LOGGER.log(Level.INFO, "Asked to provision {0} agent(s) for: {1}", new Object[]{excessWorkload, label});
List<NodeProvisioner.PlannedNode> result = new ArrayList<>();
final ECSTaskTemplate template = getTemplate(label);
if (template != null) {
String parentLabel = template.getInheritFrom();
final ECSTaskTemplate merged = template.merge(getTemplate(parentLabel));
for (int i = 1; i <= excessWorkload; i++) {
String agentName = name + "-" + label.getName() + "-" + RandomStringUtils.random(5, "bcdfghjklmnpqrstvwxz0123456789");
LOGGER.log(Level.INFO, "Will provision {0}, for label: {1}", new Object[]{agentName, label} );
result.add(
new NodeProvisioner.PlannedNode(
agentName,
Computer.threadPoolForRemoting.submit(
new ProvisioningCallback(merged, agentName)
),
1
)
);
}
}
return result.isEmpty() ? Collections.emptyList() : result;
}
/**
* Get a list of available DockerCloud clouds which are not at max
* capacity.
*
* @param label A label expression of a Job Run requiring an executor.
* @return A list of available DockerCloud clouds.
*/
protected List<DockerCloud> getAvailableDockerClouds(Label label) {
return getAllDockerClouds().stream()
.filter(cloud ->
cloud.canProvision(label) &&
(countCurrentDockerSlaves(cloud) >= 0) &&
(countCurrentDockerSlaves(cloud) < cloud.getContainerCap()))
.collect(Collectors.toList());
}
public Collection<PlannedNode> provision(Label label, int excessWorkload) {
List<PlannedNode> r = new ArrayList<PlannedNode>();
if(label!=this.label) return r; // provisioning impossible
while(excessWorkload>0) {
System.out.println("Provisioning");
numProvisioned++;
Future<Node> f = Computer.threadPoolForRemoting.submit(new Launcher(delay));
r.add(new PlannedNode(name+" #"+numProvisioned,f,1));
excessWorkload-=1;
}
return r;
}