From 384108fed2773576189998b4bb5cd620939570cd Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 26 Aug 2013 23:08:19 +0300 Subject: Implement job creation. --- utils/cmdline-client/android-build-client | 138 +++++++++++++++++++----------- 1 file changed, 86 insertions(+), 52 deletions(-) (limited to 'utils') diff --git a/utils/cmdline-client/android-build-client b/utils/cmdline-client/android-build-client index 73faa47..1bd478c 100755 --- a/utils/cmdline-client/android-build-client +++ b/utils/cmdline-client/android-build-client @@ -20,54 +20,73 @@ import optparse import getpass from xml.dom import minidom -from lxml.etree import fromstring, tostring - - -auth_headers = None - -def jenkins_rest(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) - url = options.url + jenkins_path - print url - req = urllib2.Request( - url, data, headers) - resp = urllib2.urlopen(req) - return resp.read() - -def get_job_config(job_name): - return jenkins_rest('job/' + job_name + '/config.xml') - -def set_job_config(url, configXml, extra_headers=None): - headers = {'Content-Type': 'text/xml', } - if extra_headers is not None: - headers.update(extra_headers) - _authJenkins(url, configXml, headers) - -def get_csrf_headers(): - try: - crumb_data = _authJenkins('crumbIssuer/api/json') - except urllib2.HTTPError: - # Ignore errors in case CSRF protection is not enabled - return {} - data = json.loads(crumb_data) - return {data['crumbRequestField']: data['crumb']} +class Jenkins(object): + + def __init__(self, base_url, username, passwd): + self.base = base_url + self.auth_headers = { + 'Authorization': 'Basic %s' % ( + base64.b64encode('%s:%s' % (username, passwd)))} + self.csrf = None + + def jenkins_rest(self, 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 = self.auth_headers.copy() + if extra_headers: + headers.update(extra_headers) + url = self.base + jenkins_path + print url + req = urllib2.Request( + url, data, headers) + resp = urllib2.urlopen(req) + return resp.read() + + def get_csrf_headers(self): + if self.csrf is None: + try: + crumb_data = self.jenkins_rest('crumbIssuer/api/json') + data = json.loads(crumb_data) + self.csrf = {data['crumbRequestField']: data['crumb']} + except urllib2.HTTPError: + # Ignore errors in case CSRF protection is not enabled + self.csrf = {} + return self.csrf + + def get_job_config(self, job_name): + return self.jenkins_rest('job/' + job_name + '/config.xml') + + def _post_config(self, url, config_xml): + headers = self.get_csrf_headers() + headers['Content-Type'] = 'text/xml' + return self.jenkins_rest(url, config_xml, headers) + + def set_job_config(self, job_name, config_xml): + return self._post_config('job/' + job_name + '/config.xml', config_xml) + + def create_job(self, job_name, config_xml): + return self._post_config('createItem?name=' + job_name, config_xml) + +def job2user_group(job_group): + if job_group == "linaro-android": + return "linaro-android-builders" + return job_group + +def error(msg): + print msg + sys.exit(1) def main(): - global auth_headers global options optparser = optparse.OptionParser(usage="%prog ...") optparser.add_option("--url", default="https://android-build.linaro.org/jenkins", @@ -96,13 +115,28 @@ def main(): if options.url[-1] != '/': options.url += '/' - auth_headers = { - 'Authorization': 'Basic %s' % ( - base64.encodestring('%s:%s' % (options.user, password))[:-1],), - } - - job_group, job_subname = args[1].split("/") - print get_job_config("template_" + job_group) + j = Jenkins(options.url, options.user, password) + + if args[0] == "create": + if len(args) != 3: + optparser.error("Usage: create ") + job_group, job_subname = args[1].split("/") + template = j.get_job_config("template_" + job2user_group(job_group)) + dom = minidom.parseString(template) + nodes = dom.getElementsByTagName("hudson.model.StringParameterDefinition") + assert len(nodes) == 1 + n = nodes[0].getElementsByTagName("defaultValue")[0] + build_config = open(args[2]).read() + n.childNodes[0].data = base64.encodestring(build_config) + job_conf = dom.toxml() + jenkins_job = args[1].replace("/", "_") + try: + j.create_job(jenkins_job, job_conf) + except urllib2.HTTPError, e: + error("Error creating job '%s' (job exists?)" % jenkins_job) + print "Job created successfully: %s/job/%s/" % (options.url, jenkins_job) + else: + optparser.error("Unknown command '%s'" % args[0]) if __name__ == "__main__": -- cgit v1.2.3