summaryrefslogtreecommitdiff
path: root/simplejenkinsapi
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2012-08-11 12:10:45 +0100
committerLars Wirzenius <liw@liw.fi>2012-08-11 12:10:45 +0100
commit67acf03ae11343a5299218bd14c660eeb8ff6e59 (patch)
tree8607b6e01d900992471633d2a66c932b13539a92 /simplejenkinsapi
parent9ab26c8577cc723fb947f6fa70a2a4bffdb81c7a (diff)
downloadjenkinstool-67acf03ae11343a5299218bd14c660eeb8ff6e59.tar.gz
Move Jenkins class into package, fix so ./check passes
Diffstat (limited to 'simplejenkinsapi')
-rw-r--r--simplejenkinsapi/__init__.py4
-rw-r--r--simplejenkinsapi/api.py126
2 files changed, 128 insertions, 2 deletions
diff --git a/simplejenkinsapi/__init__.py b/simplejenkinsapi/__init__.py
index 693b180..6d18b76 100644
--- a/simplejenkinsapi/__init__.py
+++ b/simplejenkinsapi/__init__.py
@@ -16,5 +16,5 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from .jobconfig import JobConfig
-
+from jobconfig import JobConfig
+from api import Jenkins
diff --git a/simplejenkinsapi/api.py b/simplejenkinsapi/api.py
new file mode 100644
index 0000000..5571298
--- /dev/null
+++ b/simplejenkinsapi/api.py
@@ -0,0 +1,126 @@
+# simplejenkinsapi/api.py -- simple job management in Jenkins
+#
+# Copyright 2012 Lars Wirzenius
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+'''Simple job management in Jenkins.
+
+This module provides tools for listing, creating, updating, and
+removing jobs in a running Jenkins instance, using its HTTP API.
+
+'''
+
+
+import httplib
+import json
+import logging
+import urlparse
+
+
+class Jenkins(object):
+
+ '''Access a running Jenkins server.'''
+
+ def __init__(self, url): # pragma: no cover
+ self._url = url
+
+ def _connect(self): # pragma: no cover
+ '''Connect to HTTP server, return httplib.HTTPConnection.'''
+ (scheme, netloc, path, params, query,
+ fragment) = urlparse.urlparse(self._url)
+ assert path == '/'
+ assert params == ''
+ assert fragment == ''
+
+ if ':' in netloc:
+ host, port = netloc.split(':', 1)
+ port = int(port)
+ else:
+ host = netloc
+ port = None
+
+ if scheme == 'https':
+ return httplib.HTTPSConnection(host, port)
+ else:
+ return httplib.HTTPConnection(host, port)
+
+ def _do(self, method, path, body='', headers={}):
+ '''Make an HTTP request, return result.
+
+ If server returned JSON, return it as a Python object.
+ Otherwise, return as string.
+
+ '''
+
+ conn = self._connect()
+ conn.request(method, path, body, headers)
+ resp = conn.getresponse()
+ text = resp.read()
+
+ logging.debug('HTTP status: %d' % resp.status)
+ logging.debug('HTTP reason: %s' % resp.reason)
+ logging.debug('HTTP text: %s' % repr(text))
+
+ ok = [httplib.OK, httplib.FOUND]
+ if resp.status not in ok: # pragma: no cover
+ raise httplib.HTTPException('Error %d (%s) from server:\n%s' %
+ (resp.status, resp.reason, text))
+
+ typ = resp.getheader('Content-Type') or 'application/octet-stream'
+ if typ == 'application/json' or typ.startswith('application/json;'):
+ return json.loads(text)
+ else:
+ return text
+
+ def list_jobs(self):
+ '''Return list of job ids on the server.'''
+
+ obj = self._do('GET', '/api/json')
+ logging.debug('obj: %s' % repr(obj))
+ return [job['name'] for job in obj['jobs']]
+
+ def delete_job(self, job_id):
+ '''Delete a job from Jenkins server, given job id.'''
+
+ self._do('POST', '/job/%s/doDelete' % job_id)
+
+ def create_job(self, job_id, config_xml):
+ '''Create a new job.
+
+ ``config_xml`` is a string containing the XML format configuration
+ of the job.
+
+ '''
+
+ self._do('POST', '/createItem?name=%s' % job_id, body=config_xml,
+ headers={'Content-Type': 'text/xml'})
+
+ def update_job(self, job_id, config_xml):
+ '''Update the configuration of a new job.
+
+ ``config_xml`` is a string containing the XML format configuration
+ of the job.
+
+ '''
+
+ self._do('POST', '/job/%s/config.xml' % job_id, body=config_xml,
+ headers={ 'Content-Type': 'text/xml' })
+
+ def get_job_config(self, job_id):
+ '''Return the XML configuration of a job.'''
+
+ return self._do('GET', '/job/%s/config.xml' % job_id)
+