public MesosSlaveInfo getMesosSlaveInfoForLabel(Label label) { if (!matchesLabel(label)) { return null; } if (label == null) { if (getLabelString() == null) { return this; } else { return null; } } if (label.matches(Label.parse(getLabelString()))) { return this; } if (!containerInfo.getDockerImageCustomizable()) { return null; } String customImage = getCustomImage(label); if (customImage == null) { return null; } return copyWithDockerImage(label.toString(), customImage); }
/** Returns slave template associated with the label */ public AzureSlaveTemplate getAzureSlaveTemplate(Label label) { for (AzureSlaveTemplate slaveTemplate : instTemplates) { if (slaveTemplate.getUseSlaveAlwaysIfAvail() == Node.Mode.NORMAL) { if (label == null || label.matches(slaveTemplate.getLabelDataSet())) { return slaveTemplate; } } else if (slaveTemplate.getUseSlaveAlwaysIfAvail() == Node.Mode.EXCLUSIVE) { if (label != null && label.matches(slaveTemplate.getLabelDataSet())) { return slaveTemplate; } } } return null; }
/** Gets {@link SlaveTemplate} that has the matching {@link Label}. */ public SlaveTemplate getTemplate(Label label) { for (SlaveTemplate t : templates) { if (t.getMode() == Node.Mode.NORMAL) { if (label == null || label.matches(t.getLabelSet())) { return t; } } else if (t.getMode() == Node.Mode.EXCLUSIVE) { if (label != null && label.matches(t.getLabelSet())) { return t; } } } return null; }
@Issue("JENKINS-26123") @Test public void noWait() throws Exception { j.createFreeStyleProject("ds").setAssignedLabel(Label.get("nonexistent")); WorkflowJob us = j.jenkins.createProject(WorkflowJob.class, "us"); us.setDefinition(new CpsFlowDefinition("build job: 'ds', wait: false")); j.assertBuildStatusSuccess(us.scheduleBuild2(0)); }
private ECSTaskTemplate getTemplate(Label label) { for (ECSTaskTemplate t : templates) { if (label == null || label.matches(t.getLabelSet())) { return t; } } return null; }
/** * Check if the label in the slave matches the provided label, either both are null or are the * same. * * @param label * @return Whether the slave label matches. */ public boolean matchesLabel(@CheckForNull Label label) { if (label == null || getLabelString() == null) { return label == null && getLabelString() == null; } if (label.matches(Label.parse(getLabelString()))) { return true; } if (containerInfo == null || !containerInfo.getDockerImageCustomizable()) { return false; } String customImage = getCustomImage(label); return customImage != null && getLabelWithoutCustomImage(label, customImage).matches(Label.parse(getLabelString())); }
private static String getCustomImage(Label label) { Matcher m = CUSTOM_IMAGE_FROM_LABEL_PATTERN.matcher(label.toString()); if (m.find()) { return m.group(1); } return null; }
/** * Determines whether the AMI of the given instance matches the AMI of template and has the * required label (if requiredLabel is non-null) */ private boolean checkInstance( PrintStream logger, Instance existingInstance, Label requiredLabel, EC2AbstractSlave[] returnNode) { logProvision(logger, "checkInstance: " + existingInstance); if (StringUtils.isNotBlank(getIamInstanceProfile())) { if (existingInstance.getIamInstanceProfile() != null) { if (!existingInstance.getIamInstanceProfile().getArn().equals(getIamInstanceProfile())) { logProvision(logger, " false - IAM Instance profile does not match"); return false; } // Match, fall through } else { logProvision(logger, " false - Null IAM Instance profile"); return false; } } if (existingInstance .getState() .getName() .equalsIgnoreCase(InstanceStateName.Terminated.toString()) || existingInstance .getState() .getName() .equalsIgnoreCase(InstanceStateName.ShuttingDown.toString())) { logProvision(logger, " false - Instance is terminated or shutting down"); return false; } // See if we know about this and it has capacity for (EC2AbstractSlave node : NodeIterator.nodes(EC2AbstractSlave.class)) { if (node.getInstanceId().equals(existingInstance.getInstanceId())) { logProvision(logger, "Found existing corresponding Jenkins slave: " + node.getInstanceId()); if (!node.toComputer().isPartiallyIdle()) { logProvision(logger, " false - Node is not partially idle"); return false; } // REMOVEME - this was added to force provision to work, but might not allow // stopped instances to be found - need to investigate further else if (false && node.toComputer().isOffline()) { logProvision(logger, " false - Node is offline"); return false; } else if (requiredLabel != null && !requiredLabel.matches(node.getAssignedLabels())) { logProvision(logger, " false - we need a Node having label " + requiredLabel); return false; } else { logProvision(logger, " true - Node has capacity - can use it"); returnNode[0] = node; return true; } } } logProvision(logger, " true - Instance has no node, but can be used"); return true; }
public EcsTaskTemplate getTemplate(Label label) { if (label == null && templates.size() > 0) { return templates.get(0); } for (EcsTaskTemplate t : templates) { if (label.matches(t.getLabelSet())) { return t; } } return null; }
@Test public void testLabelExpression() throws Exception { setUpCloud(LABEL1 + " " + LABEL2); assertEquals(true, ac.canProvision(Label.parseExpression(LABEL1 + " || " + LABEL2))); assertEquals(true, ac.canProvision(Label.parseExpression(LABEL1 + " && " + LABEL2))); assertEquals(true, ac.canProvision(Label.parseExpression(LABEL1 + " || aaa"))); assertEquals(false, ac.canProvision(Label.parseExpression(LABEL1 + " && aaa"))); assertEquals(false, ac.canProvision(Label.parseExpression("aaa || bbb"))); assertEquals(false, ac.canProvision(Label.parseExpression("aaa || bbb"))); }
/** Initializes data structure that we don't persist. */ public Object readResolve() { if (configVersion < 1) { try { convert1(); } catch (Throwable t) { LOGGER.log(Level.SEVERE, "Can't convert old values to new (double conversion?): ", t); } configVersion = 1; } try { labelSet = Label.parse(labelString); // fails sometimes under debugger } catch (Throwable t) { LOGGER.log(Level.SEVERE, "Can't parse labels: ", t); } return this; }
@DataBoundConstructor public DockerTemplate( DockerTemplateBase dockerTemplateBase, String labelString, String remoteFs, String remoteFsMapping, String instanceCapStr) { this.dockerTemplateBase = dockerTemplateBase; this.labelString = Util.fixNull(labelString); this.remoteFs = Strings.isNullOrEmpty(remoteFs) ? "/home/jenkins" : remoteFs; this.remoteFsMapping = remoteFsMapping; if (instanceCapStr.equals("")) { this.instanceCap = Integer.MAX_VALUE; } else { this.instanceCap = Integer.parseInt(instanceCapStr); } labelSet = Label.parse(labelString); }
/** Initializes data structure that we don't persist. */ protected Object readResolve() { labelSet = Label.parse(labels); securityGroupSet = parseSecurityGroups(); /** * In releases of this plugin prior to 1.18, template-specific instance caps could be configured * but were not enforced. As a result, it was possible to have the instance cap for a template * be configured to 0 (zero) with no ill effects. Starting with version 1.18, template-specific * instance caps are enforced, so if a configuration has a cap of zero for a template, no * instances will be launched from that template. Since there is no practical value of * intentionally setting the cap to zero, this block will override such a setting to a value * that means 'no cap'. */ if (instanceCap == 0) { instanceCap = Integer.MAX_VALUE; } if (amiType == null) { amiType = new UnixData(rootCommandPrefix, sshPort); } return this; }
public boolean canProvision(Label label) { AzureSlaveTemplate template = getAzureSlaveTemplate(label); // return false if there is no template if (template == null) { if (label != null) { LOGGER.info( "Azurecloud: canProvision: template not found for label " + label.getDisplayName()); } else { LOGGER.info( "Azurecloud: canProvision: template not found for empty label. All templates exclusive to jobs that require that template."); } return false; } else if (template.getTemplateStatus().equalsIgnoreCase(Constants.TEMPLATE_STATUS_DISBALED)) { LOGGER.info( "Azurecloud: canProvision: template " + template.getTemplateName() + " is marked has disabled, cannot provision slaves"); return false; } else { return true; } }
@Override public Collection<PlannedNode> provision(Label label, int excessWorkload) { try { // Count number of pending executors from spot requests for (EC2SpotSlave n : NodeIterator.nodes(EC2SpotSlave.class)) { // If the slave is online then it is already counted by Jenkins // We only want to count potential additional Spot instance // slaves if (n.getComputer().isOffline() && label.matches(n.getAssignedLabels())) { DescribeSpotInstanceRequestsRequest dsir = new DescribeSpotInstanceRequestsRequest() .withSpotInstanceRequestIds(n.getSpotInstanceRequestId()); for (SpotInstanceRequest sir : connect().describeSpotInstanceRequests(dsir).getSpotInstanceRequests()) { // Count Spot requests that are open and still have a // chance to be active // A request can be active and not yet registered as a // slave. We check above // to ensure only unregistered slaves get counted if (sir.getState().equals("open") || sir.getState().equals("active")) { excessWorkload -= n.getNumExecutors(); } } } } LOGGER.log(Level.INFO, "Excess workload after pending Spot instances: " + excessWorkload); List<PlannedNode> r = new ArrayList<PlannedNode>(); final SlaveTemplate t = getTemplate(label); int amiCap = t.getInstanceCap(); while (excessWorkload > 0) { if (!addProvisionedSlave(t.ami, amiCap, t.description)) { break; } r.add( new PlannedNode( t.getDisplayName(), Computer.threadPoolForRemoting.submit( new Callable<Node>() { public Node call() throws Exception { // TODO: record the output somewhere try { EC2AbstractSlave s = t.provision(StreamTaskListener.fromStdout()); Hudson.getInstance().addNode(s); // EC2 instances may have a long init script. If we // declare // the provisioning complete by returning without // the connect // operation, NodeProvisioner may decide that it // still wants // one more instance, because it sees that (1) all // the slaves // are offline (because it's still being launched) // and // (2) there's no capacity provisioned yet. // // deferring the completion of provisioning until // the launch // goes successful prevents this problem. s.toComputer().connect(false).get(); return s; } finally { decrementAmiSlaveProvision(t.ami); } } }), t.getNumExecutors())); excessWorkload -= t.getNumExecutors(); } return r; } catch (AmazonClientException e) { LOGGER.log(Level.WARNING, "Failed to count the # of live instances on EC2", e); return Collections.emptyList(); } }
@Override public Label getAssignedLabel(SubTask task) { return Label.get(label); }
/** * Initializes data structure that we don't persist. */ protected Object readResolve() { labelSet = Label.parse(labelString); return this; }
public Node call() throws Exception { String uniq = Long.toHexString(System.nanoTime()); ECSSlave slave = new ECSSlave( ECSCloud.this, name + "-" + uniq, template.getRemoteFSRoot(), label == null ? null : label.toString(), new JNLPLauncher()); Jenkins.getInstance().addNode(slave); LOGGER.log(Level.INFO, "Created Slave: {0}", slave.getNodeName()); final AmazonECSClient client = getAmazonECSClient(); LOGGER.log(Level.INFO, "Selected Region: {0}", getRegionName()); client.setRegion(getRegion(getRegionName())); Collection<String> command = getDockerRunCommand(slave); String definitionArn = template.getTaskDefinitionArn(); slave.setTaskDefinitonArn(definitionArn); final RunTaskResult runTaskResult = client.runTask( new RunTaskRequest() .withTaskDefinition(definitionArn) .withOverrides( new TaskOverride() .withContainerOverrides( new ContainerOverride() .withName("jenkins-slave") .withCommand(command))) .withCluster(cluster)); if (!runTaskResult.getFailures().isEmpty()) { LOGGER.log( Level.WARNING, "Slave {0} - Failure to run task with definition {1} on ECS cluster {2}", new Object[] {slave.getNodeName(), definitionArn, cluster}); for (Failure failure : runTaskResult.getFailures()) { LOGGER.log( Level.WARNING, "Slave {0} - Failure reason={1}, arn={2}", new Object[] {slave.getNodeName(), failure.getReason(), failure.getArn()}); } throw new AbortException("Failed to run slave container " + slave.getNodeName()); } String taskArn = runTaskResult.getTasks().get(0).getTaskArn(); LOGGER.log( Level.INFO, "Slave {0} - Slave Task Started : {1}", new Object[] {slave.getNodeName(), taskArn}); slave.setTaskArn(taskArn); int i = 0; int j = 100; // wait 100 seconds // now wait for slave to be online for (; i < j; i++) { if (slave.getComputer() == null) { throw new IllegalStateException( "Slave " + slave.getNodeName() + " - Node was deleted, computer is null"); } if (slave.getComputer().isOnline()) { break; } LOGGER.log( Level.FINE, "Waiting for slave {0} (ecs task {1}) to connect ({2}/{3}).", new Object[] {slave.getNodeName(), taskArn, i, j}); Thread.sleep(1000); } if (!slave.getComputer().isOnline()) { throw new IllegalStateException( "ECS Slave " + slave.getNodeName() + " (ecs task " + taskArn + ") is not connected after " + j + " seconds"); } LOGGER.log( Level.INFO, "ECS Slave " + slave.getNodeName() + " (ecs task {0}) connected", taskArn); return slave; }
private static Label getLabelWithoutCustomImage(Label label, String customDockerImage) { return Label.get(label.toString().replace(CUSTOM_IMAGE_SEPARATOR + customDockerImage, "")); }
public static void startSeleniumNode(Computer c, TaskListener listener, String conf) throws IOException, InterruptedException { LOGGER.fine("Examining if we need to start Selenium Grid Node"); final PluginImpl p = Hudson.getInstance().getPlugin(PluginImpl.class); final String exclusions = p.getExclusionPatterns(); List<String> exclusionPatterns = new ArrayList<String>(); if (StringUtils.hasText(exclusions)) { exclusionPatterns = Arrays.asList(exclusions.split(SEPARATOR)); } if (exclusionPatterns.size() > 0) { // loop over all the labels and check if we need to exclude a node // based on the exlusionPatterns for (Label label : c.getNode().getAssignedLabels()) { for (String pattern : exclusionPatterns) { if (label.toString().matches(pattern)) { LOGGER.fine( "Node " + c.getNode().getDisplayName() + " is excluded from Selenium Grid because its label '" + label + "' matches exclusion pattern '" + pattern + "'"); return; } } } } final String masterName = PluginImpl.getMasterHostName(); if (masterName == null) { listener .getLogger() .println( "Unable to determine the host name of the master. Skipping Selenium execution. " + "Please " + HyperlinkNote.encodeTo("/configure", "configure the Jenkins URL") + " from the system configuration screen."); return; } // make sure that Selenium Hub is started before we start RCs. try { p.waitForHubLaunch(); } catch (ExecutionException e) { throw new IOException2("Failed to wait for the Hub launch to complete", e); } List<SeleniumGlobalConfiguration> confs = getPlugin().getGlobalConfigurationForComputer(c); if (confs == null || confs.size() == 0) { LOGGER.fine( "There is no matching configurations for that computer. Skipping selenium execution."); return; } String nodehost = c.getHostName(); if (nodehost == null) { LOGGER.warning("Unable to determine node's hostname. Skipping"); return; } listener .getLogger() .println( "Starting Selenium nodes on " + ("".equals(c.getName()) ? "(master)" : c.getName())); for (SeleniumGlobalConfiguration config : confs) { if ((conf != null && config.getName().equals(conf)) || conf == null) { try { config.start(c, listener); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
public String getShortDescription() { return Messages.Queue_WaitingForNextAvailableExecutorOn(label.getName()); }
public void testQuote() { Label l = jenkins.getLabel("\"abc\\\\\\\"def\""); assertEquals("abc\\\"def", l.getName()); }
public String getShortDescription() { return Messages.Queue_AllNodesOffline(label.getName()); }