diff options
author | Paul Sokolovsky <paul.sokolovsky@linaro.org> | 2011-11-18 05:07:26 +0200 |
---|---|---|
committer | Paul Sokolovsky <paul.sokolovsky@linaro.org> | 2011-11-18 05:07:26 +0200 |
commit | 7cfa06224f6fdf02a5ce5dc543c031a8f93df02b (patch) | |
tree | 8dbfd8f5098e9b1bc1781d3fb587c243d26b7867 /utils | |
parent | 4137e1fae265afbbf584dd13291ace986ff9e316 (diff) |
Create new utils dir, move mange-jobs util there.
Diffstat (limited to 'utils')
-rw-r--r-- | utils/mangle-jobs/add-logparser.mangle | 20 | ||||
-rwxr-xr-x | utils/mangle-jobs/mangle-jobs | 127 | ||||
-rw-r--r-- | utils/mangle-jobs/reset-cron.mangle | 8 | ||||
-rw-r--r-- | utils/mangle-jobs/test.mangle | 6 | ||||
-rw-r--r-- | utils/mangle-jobs/update-artifacts.mangle | 5 | ||||
-rw-r--r-- | utils/mangle-jobs/update-jobs.mangle | 9 |
6 files changed, 175 insertions, 0 deletions
diff --git a/utils/mangle-jobs/add-logparser.mangle b/utils/mangle-jobs/add-logparser.mangle new file mode 100644 index 0000000..597a66e --- /dev/null +++ b/utils/mangle-jobs/add-logparser.mangle @@ -0,0 +1,20 @@ +# Add Log Parser plugin application to jobs + +#from lxml.etree import Element +from lxml.etree import fromstring + +def mangle(tree): + if tree.xpath("//hudson.plugins.logparser.LogParserPublisher"): + # Already there + return + tag = tree.xpath('//publishers')[0] + node = fromstring("""\ + <hudson.plugins.logparser.LogParserPublisher> + <unstableOnWarning>false</unstableOnWarning> + <failBuildOnError>false</failBuildOnError> + <parsingRulesPath>/var/lib/jenkins/userContent/android.parse</parsingRulesPath> + </hudson.plugins.logparser.LogParserPublisher> +""") + tag.append(node) + node.getprevious().tail += " " + node.tail = "\n " diff --git a/utils/mangle-jobs/mangle-jobs b/utils/mangle-jobs/mangle-jobs new file mode 100755 index 0000000..cd71ec6 --- /dev/null +++ b/utils/mangle-jobs/mangle-jobs @@ -0,0 +1,127 @@ +#!/usr/bin/python +"""Helper to mass-edit jobs in jenkins. + +""" + +############################################################################### +# Copyright (c) 2011 Linaro +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################### + +import base64 +from contextlib import nested +import json +import os +import sys +from tempfile import NamedTemporaryFile +import urllib2 +import optparse + +from lxml.etree import fromstring, tostring + + +optparser = optparse.OptionParser(usage="%prog <mangle script>") +optparser.add_option("--user", + help="Jenkins username") +optparser.add_option("--passwd-file", metavar="FILE", + help="File holding Jenkins password") +optparser.add_option("--really", action="store_true", + help="Actually perform changes") +optparser.add_option("--limit", type="int", default=-1, + help="Change at most LIMIT jobs") +optparser.add_option("--file", + help="Process a file instead of all jobs on a remote server") + +options, args = optparser.parse_args(sys.argv[1:]) +if len(args) != 1: + optparser.error("Wrong number of arguments") + +d = {} +execfile(args[0], d, d) +mangler = d['mangle'] + +password = None +if options.passwd_file: + password = open(options.passwd_file).read().strip() +auth_headers = { + 'Authorization': 'Basic %s' % ( + base64.encodestring('%s:%s' % (options.user, password))[:-1],), + } + +def _authJenkins(jenkins_path, data=None, extra_headers=None): + """Make an authenticated request to jenkins. + + @param jenkins_path: The path on the Jenkins instance to make the request + to. + @param data: Data to include in the request (if this is not None the + request will be a POST). + @param extra_headers: A dictionary of extra headers that will passed in + addition to Authorization. + @raises urllib2.HTTPError: If the response is not a HTTP 200. + @returns: the body of the response. + """ + headers = auth_headers.copy() + if extra_headers: + headers.update(extra_headers) + req = urllib2.Request( + 'http://localhost:9090/jenkins/' + jenkins_path, data, headers) + resp = urllib2.urlopen(req) + return resp.read() + +def getJobConfig(job_name): + return _authJenkins('job/' + job_name + '/config.xml') + +def postConfig(url, configXml): + _authJenkins(url, configXml, {'Content-Type': 'text/xml'}) + +def render_xml(tree): + text = tostring(tree, xml_declaration=True, encoding='UTF-8') + line1, rest = text.split("\n", 1) + line1 = line1.replace("'", '"') + return line1 + rest + +def show_diff(old, new): + with nested(NamedTemporaryFile(), NamedTemporaryFile()) as (a, b): + a.write(old) + b.write(new) + a.flush(); b.flush() + os.system('diff -u %s %s' % (a.name, b.name)) + print + +def process_remote_jenkins(): + jobs = json.load(urllib2.urlopen('http://localhost:9090/jenkins/api/json?tree=jobs[name]')) + names = [job['name'] for job in jobs['jobs']] + names = [name for name in names if name == 'blank' or '_' in name] + limit = options.limit + for name in names: + if limit == 0: + break + limit -= 1 + print "Processing:" + name + sys.stdout.flush() + text = getJobConfig(name) + tree = fromstring(text) + mangler(tree) + new_text = render_xml(tree) + if not options.really: + show_diff(text, new_text) + else: + if type(new_text) == type(u""): + new_text = new_text.encode("utf8") + postConfig(str('job/' + name + '/config.xml'), new_text) + +def main(): + if options.file: + text = open(options.file).read() + tree = fromstring(text) + mangler(tree) + new_text = render_xml(tree) + show_diff(text, new_text) + else: + process_remote_jenkins() + +if __name__ == "__main__": + main() diff --git a/utils/mangle-jobs/reset-cron.mangle b/utils/mangle-jobs/reset-cron.mangle new file mode 100644 index 0000000..3848ac4 --- /dev/null +++ b/utils/mangle-jobs/reset-cron.mangle @@ -0,0 +1,8 @@ +# Reset any triggers of a job, cron triggers in particular (but not limited) +# This is useful for sandboxes to avoid unexpected cron jobs runs + +def mangle(tree): + tag = tree.xpath('//triggers')[0] + for t in tag: + tag.remove(t) + tag.text = None diff --git a/utils/mangle-jobs/test.mangle b/utils/mangle-jobs/test.mangle new file mode 100644 index 0000000..9fbcaa2 --- /dev/null +++ b/utils/mangle-jobs/test.mangle @@ -0,0 +1,6 @@ + +def mangle(tree): + tags = tree.xpath('/project/description') + if not tags: return + tag = tags[0] + tag.text = 'Excitingly created.' diff --git a/utils/mangle-jobs/update-artifacts.mangle b/utils/mangle-jobs/update-artifacts.mangle new file mode 100644 index 0000000..33c8066 --- /dev/null +++ b/utils/mangle-jobs/update-artifacts.mangle @@ -0,0 +1,5 @@ +new_value = "build/out/target/*/*/*.img,build/out/target/*/*/*.tar.bz2,build/out/target/*/*/MD5SUMS,build/out/*.tar.bz2,build/out/*.xml,build/out/*_config,build/out/lava-job-info" + +def mangle(tree): + tags = tree.xpath('/project/publishers/hudson.tasks.ArtifactArchiver/artifacts') + tags[0].text = new_value diff --git a/utils/mangle-jobs/update-jobs.mangle b/utils/mangle-jobs/update-jobs.mangle new file mode 100644 index 0000000..a83d815 --- /dev/null +++ b/utils/mangle-jobs/update-jobs.mangle @@ -0,0 +1,9 @@ +new_cmd = '''\ +rm -rf build-tools +bzr get http://bazaar.launchpad.net/~linaro-infrastructure/linaro-android-build-tools/trunk build-tools +build-tools/node/build us-east-1.ec2-git-mirror.linaro.org "$CONFIG" +''' + +def mangle(tree): + tags = tree.xpath('/project/builders/hudson.tasks.Shell/command') + tags[0].text = new_cmd |