Skip to content

Instantly share code, notes, and snippets.

@mheiges
Created April 2, 2012 19:09
Show Gist options
  • Save mheiges/2286418 to your computer and use it in GitHub Desktop.
Save mheiges/2286418 to your computer and use it in GitHub Desktop.
Groovy build step for puppet-client-manager
/* Groovy script for Jenkins' puppet-client-manager job
to trigger downstream execution of puppet clients.
https://ci.apidb.org/job/puppet-client-manager
*/
import hudson.model.*
import hudson.FilePath
import hudson.FilePath.FileCallable
import hudson.remoting.VirtualChannel
import java.io.OutputStream
/* ****************************************************************************************
CONFIGURATION
/* **************************************************************************************** */
// replace this hard-coded list with a lookup from <somewhere>
def hosts = [
"apricot.rcc.uga.edu",
"aprium.rcc.uga.edu",
"ares1.pcbi.upenn.edu",
/** "ares2.pcbi.upenn.edu",
"ares3.pcbi.upenn.edu",
"blender.pcbi.upenn.edu",
"caper.rcc.uga.edu",
"cassini.pcbi.upenn.edu",
"exocarp.rcc.uga.edu",
"gattaca.pcbi.upenn.edu",
"grapple.ovpr.uga.edu",
"lexicon1.pcbi.upenn.edu",
"loquat.rcc.uga.edu",
"mango.ctegd.uga.edu",
"medlar.rcc.uga.edu",
"meme.pcbi.upenn.edu",
"olive.rcc.uga.edu",
"pitaya.rcc.uga.edu", **/
"rubus.rcc.uga.edu"
]
// Downstream jobs having a name of downstreamProjectNamePrefix + host will be run
def downstreamProjectNamePrefix = "puppet-run-"
// Checkbox parameter in the project that runs this script. If true, this script
// will run downstream jobs for each host listed above.
def runParamName = "Run_client_jobs"
// Build summary goes in notesFilName to be picked up by the show-build-notes plugin
def notesFileName = "jenkins-run-notes.html"
/* **************************************************************************************** */
def upstreamBuild = Thread.currentThread().executable
def params = upstreamBuild.getAction(hudson.model.ParametersAction.class)
if (params == null) {
println "This does not look like a parameterized job. I'm expecting a parameter named " +
runParamName + ". Quiting."
return false
}
def runClients = params.createVariableResolver(upstreamBuild).resolve(runParamName)
if (runClients == null) {
println "I did not find a parameter named " + runParamName + ". Quiting."
return false
}
def futureMap = [:]
def workspace = upstreamBuild.workspace
// standard file writes occur on the master where this groovy script actually runs. To write to
// the slave's workspace, we use jenkins' FilePath remoting feature.
def notesFilePath = new FilePath(workspace.getChannel(), workspace.getRemote() + "/" + notesFileName)
def loginfo = new StringBuilder()
if ( runClients != "true" ) {
println runParamName + " is false. No client jobs run"
return // (do not System.exit(), that causes Jenkins process to exit)
}
def jenkins = hudson.model.Hudson.instance
def template = jenkins.getItem("puppet-run-template")
for (host in hosts) {
def downstreamProjectName = downstreamProjectNamePrefix + host
def downstreamProject = jenkins.getJob(downstreamProjectName)
// Create project if needed
if (downstreamProject == null ) {
println "Creating new downstream job, " + downstreamProjectName
downstreamProject = jenkins.copy(template, downstreamProjectName)
downstreamProject.setDescription("runs puppetd on " + host)
downstreamProject.save()
downstreamProject.enable()
}
// only FreeStyle projects with desired name prefix, excluding template
if ( ! (downstreamProject instanceof hudson.model.FreeStyleProject)) { continue }
if ( ! downstreamProjectName.startsWith(downstreamProjectNamePrefix)) { continue }
if (downstreamProjectName.equals(downstreamProjectNamePrefix + "template")) { continue }
if (downstreamProject.disabled) {
println downstreamProjectName + "is disabled. Skipping."
continue
}
future = downstreamProject.scheduleBuild2(0, new Cause.UpstreamCause( upstreamBuild ))
futureMap[downstreamProjectName] = future
println "Queued " + downstreamProjectName
}
println "waiting for downstream jobs to complete\n"
/** loop over Future jobs in queue, reporting results as
builds are completed
**/
while (futureMap.size() > 0) {
sleep(2000)
iterator = futureMap.entrySet().iterator()
while (iterator.hasNext()) {
entry = iterator.next()
future = entry.value
if ( ! future.isDone()) {
continue
}
downstreamBuild=future.get()
if (downstreamBuild.result.isWorseThan(Result.SUCCESS)) {
upstreamBuild.setResult(Result.UNSTABLE)
}
// this goes in a file for use by show-build-notes plugin
loginfo = loginfo.append(makeSummaryNotes())
// this prints to the Console
println hudson.console.HyperlinkNote.encodeTo("/" + downstreamBuild.getUrl() + "console",
downstreamBuild.getFullDisplayName() ) + " " + " at " + downstreamBuild.time + " - " + downstreamBuild.result
iterator.remove()
}
}
notesFilePath.write(loginfo.toString(), "UTF-8")
/**
* returns HTML formatted notes
**/
def makeSummaryNotes() {
def color = "black"
if (downstreamBuild.result.equals(Result.FAILURE)) {
color = "red"
}
def name = downstreamBuild.getFullDisplayName();
// client host name and build number from string like "puppet-run-ares1.pcbi.upenn.edu #30"
def client = name.tokenize("-").get(2)
return "<a href='/" + downstreamBuild.getUrl() + "console'>" +
client + "</a> " +
" - <font color='" + color + "'>" + downstreamBuild.result + "</font><br>\n"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment