From 82ad53f82125b4ac3f7e13340fe35b8bcf96a5b9 Mon Sep 17 00:00:00 2001 From: Aleksey Maksimov Date: Tue, 2 Jul 2013 18:16:18 +0800 Subject: [PATCH] Added ability to create nested views --- jenkinsapi/jenkins.py | 3 +++ jenkinsapi/view.py | 40 +++++++++++++++++++++++++++------------- jenkinsapi/views.py | 41 ++++++++++++++++++++++++++++------------- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/jenkinsapi/jenkins.py b/jenkinsapi/jenkins.py index 66e6585..08d917b 100644 --- a/jenkinsapi/jenkins.py +++ b/jenkinsapi/jenkins.py @@ -64,6 +64,9 @@ class Jenkins(JenkinsBase): def get_jenkins_obj(self): return self + def get_jenkins_obj_from_url(self, url): + return Jenkins(url, self.username, self.password, self.requester) + def get_create_url(self): # This only ever needs to work on the base object return '%s/createItem' % self.baseurl diff --git a/jenkinsapi/view.py b/jenkinsapi/view.py index cf0e992..6401405 100644 --- a/jenkinsapi/view.py +++ b/jenkinsapi/view.py @@ -1,7 +1,8 @@ +from urlparse import urlparse from jenkinsapi.jenkinsbase import JenkinsBase from jenkinsapi.job import Job -import logging import urllib +import logging log = logging.getLogger(__name__) @@ -73,23 +74,30 @@ class View(JenkinsBase): """ Add job to a view - :param str_job_name: name of the job to be added + :param job_name: name of the job to be added :param job: Job object to be added :return: True if job has been added, False if job already exists or job not known to Jenkins """ if not job: if str_job_name in self.get_job_dict(): - log.error('Job %s is already in the view %s' % + log.warn('Job %s is already in the view %s' % (str_job_name, self.name)) return False - elif not self.get_jenkins_obj().has_job(str_job_name): - print self.get_jenkins_obj()._data - log.error('Job "%s" is not known to Jenkins' % str_job_name) - return False - - job = self.jenkins_obj.get_job(str_job_name) - + else: + # Since this call can be made from nested view, + # which doesn't have any jobs, we can miss existing job + # Thus let's create top level Jenkins and ask him + # http://jenkins:8080/view/CRT/view/CRT-FB/view/CRT-SCRT-1301/ + top_jenkins = self.get_jenkins_obj().get_jenkins_obj_from_url( + self.baseurl.split('view/')[0]) + if not top_jenkins.has_job(str_job_name): + log.error('Job "%s" is not known to Jenkins' % str_job_name) + return False + else: + job = top_jenkins.get_job(str_job_name) + + log.info('Creating job %s in view %s' % (str_job_name, self.name)) jobs = self._data.setdefault('jobs', []) data = { "description":"", @@ -113,11 +121,17 @@ class View(JenkinsBase): "Submit":"OK", } data["name"] = self.name + # Add existing jobs (if any) for job_name in self.get_job_dict().keys(): - data[job_name]='on' + data[job_name] = 'on' + + # Add new job + data[job.name] = 'on' + data['json'] = data.copy() - self.jenkins_obj.requester.post_and_confirm_status( - '%sconfigSubmit' % self.baseurl, urllib.urlencode(data)) + data = urllib.urlencode(data) + self.get_jenkins_obj().requester.post_and_confirm_status( + '%s/configSubmit' % self.baseurl, data=data) self.poll() log.debug('Job "%s" has been added to a view "%s"' % (job.name, self.name)) diff --git a/jenkinsapi/views.py b/jenkinsapi/views.py index e9d60bb..8aaabd2 100644 --- a/jenkinsapi/views.py +++ b/jenkinsapi/views.py @@ -1,8 +1,19 @@ +import logging import json from jenkinsapi.view import View from jenkinsapi.exceptions import UnknownView +log = logging.getLogger(__name__) + class Views(object): + + # TODO @lechat 20130702: Add check that plugin for view actually exists in Jenkins + LIST_VIEW = 'hudson.model.ListView' + NESTED_VIEW = 'hudson.plugins.nested_view.NestedView' + MY_VIEW = 'hudson.model.MyView' + DASHBOARD_VIEW = 'hudson.plugins.view.dashboard.Dashboard' + PIPELINE_VIEW = 'au.com.centrumsystems.hudson.plugin.buildpipeline.BuildPipelineView' + """ An abstraction on a Jenkins object's views """ @@ -17,8 +28,9 @@ class Views(object): if view_name == 'All': raise ValueError('Cannot delete this view: %s' % view_name) - self[view_name].delete() - self.jenkins.poll + if view_name in self: + self[view_name].delete() + self.jenkins.poll() def __setitem__(self, name, value): raise NotImplementedError() @@ -30,7 +42,8 @@ class Views(object): row['url'], row['name'], self.jenkins) - raise UnknownView(view_name) + else: + return None def __iteritems__(self): """ @@ -68,27 +81,29 @@ class Views(object): self.jenkins.poll() return self - def create(self, str_view_name): + def create(self, view_name, view_type=LIST_VIEW): """ Create a view - :param str_view_name: name of new view, str + :param view_name: name of new view, str :param person: Person name (to create personal view), str :return: new View obj or None if view was not created """ + log.info('Creating "%s" view "%s"' % (view_type, view_name)) #url = urlparse.urljoin(self.baseurl, "user/%s/my-views/" % person) if person else self.baseurl - try: - return self[str_view_name] - except KeyError: - pass + + if view_name in self: + log.warn('View "%s" already exists' % view_name) + return self[view_name] + url = '%s/createView' % self.jenkins.baseurl headers = {'Content-Type': 'application/x-www-form-urlencoded'} data = { - "name": str_view_name, - "mode": "hudson.model.ListView", + "name": view_name, + "mode": view_type, "Submit": "OK", - "json": json.dumps({"name": str_view_name, "mode": "hudson.model.ListView"}) + "json": json.dumps({"name": view_name, "mode": view_type}) } self.jenkins.requester.post_and_confirm_status(url, data=data, headers=headers) self.jenkins.poll() - return self[str_view_name] + return self[view_name] -- 2.7.4