From 09ca9e58cc0c17d6f59109208971e9bef57352d2 Mon Sep 17 00:00:00 2001 From: Aleksey Maksimov Date: Thu, 25 Jul 2013 00:19:15 +0800 Subject: [PATCH] Added ability to query for installed plugins --- jenkinsapi/jenkins.py | 15 +++- jenkinsapi/plugin.py | 7 ++ jenkinsapi/plugins.py | 53 +++++++++++ jenkinsapi_tests/unittests/test_jenkins.py | 17 ++++ jenkinsapi_tests/unittests/test_plugins.py | 100 +++++++++++++++++++++ 5 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 jenkinsapi/plugin.py create mode 100644 jenkinsapi/plugins.py create mode 100644 jenkinsapi_tests/unittests/test_plugins.py diff --git a/jenkinsapi/jenkins.py b/jenkinsapi/jenkins.py index 08d917b..334b49d 100644 --- a/jenkinsapi/jenkins.py +++ b/jenkinsapi/jenkins.py @@ -7,6 +7,7 @@ from jenkinsapi.job import Job from jenkinsapi.node import Node from jenkinsapi.view import View from jenkinsapi.nodes import Nodes +from jenkinsapi.plugins import Plugins from jenkinsapi.views import Views from jenkinsapi.queue import Queue from jenkinsapi.fingerprint import Fingerprint @@ -14,10 +15,9 @@ from jenkinsapi.jenkinsbase import JenkinsBase from jenkinsapi.utils.requester import Requester from jenkinsapi.exceptions import UnknownJob, JenkinsAPIException - - log = logging.getLogger(__name__) + class Jenkins(JenkinsBase): """ Represents a jenkins environment. @@ -315,3 +315,14 @@ class Jenkins(JenkinsBase): self.requester.get_and_confirm_status(url) return Node(nodename=name, baseurl=self.get_node_url(nodename=name), jenkins_obj=self) + + def get_plugins_url(self): + # This only ever needs to work on the base object + return '%s/pluginManager/api/python?depth=1' % self.baseurl + + def get_plugins(self): + url = self.get_plugins_url() + return Plugins(url, self) + + def has_plugin(self, plugin_name): + return plugin_name in self.get_plugins() diff --git a/jenkinsapi/plugin.py b/jenkinsapi/plugin.py new file mode 100644 index 0000000..b64a706 --- /dev/null +++ b/jenkinsapi/plugin.py @@ -0,0 +1,7 @@ +class Plugin(object): + def __init__(self, plugin_dict): + assert(isinstance(plugin_dict, dict)) + self.__dict__ = plugin_dict + + def __eq__(self, other): + return self.__dict__ == other.__dict__ diff --git a/jenkinsapi/plugins.py b/jenkinsapi/plugins.py new file mode 100644 index 0000000..06ae7f1 --- /dev/null +++ b/jenkinsapi/plugins.py @@ -0,0 +1,53 @@ +import urllib +import logging + +from jenkinsapi.jenkinsbase import JenkinsBase +from jenkinsapi.plugin import Plugin + + +log = logging.getLogger(__name__) + + +class Plugins(JenkinsBase): + def __init__(self, url, jenkins_obj): + self.jenkins_obj = jenkins_obj + JenkinsBase.__init__(self, url) + # print 'DEBUG: Plugins._data=', self._data + + def get_jenkins_obj(self): + return self.jenkins_obj + + def _poll(self): + return self.get_data(self.baseurl) + + def keys(self): + return self.get_plugins_dict().keys() + + def iteritems(self): + return self._get_plugins() + + def values(self): + return [a[1] for a in self.iteritems()] + + def _get_plugins(self): + if not 'plugins' in self._data: + pass + else: + for p_dict in self._data["plugins"]: + yield p_dict["shortName"], Plugin(p_dict) + + def get_plugins_dict(self): + return dict(self._get_plugins()) + + def __len__(self): + return len(self.get_plugins_dict().keys()) + + def __getitem__(self, plugin_name): + return self.get_plugins_dict().get(plugin_name, None) + + def __contains__(self, plugin_name): + """ + True if plugin_name is the name of a defined plugin + """ + return plugin_name in self.keys() + diff --git a/jenkinsapi_tests/unittests/test_jenkins.py b/jenkinsapi_tests/unittests/test_jenkins.py index b80e54e..d42b9d3 100644 --- a/jenkinsapi_tests/unittests/test_jenkins.py +++ b/jenkinsapi_tests/unittests/test_jenkins.py @@ -4,6 +4,7 @@ import unittest from jenkinsapi.utils.requester import Requester from jenkinsapi.exceptions import JenkinsAPIException from jenkinsapi.jenkins import Jenkins, JenkinsBase, Job +from jenkinsapi.plugins import Plugins class TestJenkins(unittest.TestCase): @@ -355,6 +356,22 @@ class TestJenkinsURLs(unittest.TestCase): self.assertEquals( J.get_create_url(), 'http://localhost:8080/createItem') + @mock.patch.object(Jenkins, '_poll') + @mock.patch.object(Plugins, '_poll') + def test_has_plugin(self, _p_poll, _poll): + _poll.return_value = {} + _p_poll.return_value = {'plugins': [ + {'deleted': False, 'hasUpdate': True, 'downgradable': False, + 'dependencies': [{}, {}, {}, {}], + 'longName': 'Jenkins Subversion Plug-in', 'active': True, + 'shortName': 'subversion', 'backupVersion': None, + 'url': 'http://wiki.jenkins-ci.org/display/JENKINS/Subversion+Plugin', + 'enabled': True, 'pinned': False, 'version': '1.45', + 'supportsDynamicLoad': 'MAYBE', 'bundled': True}]} + + J = Jenkins('http://localhost:8080/', + username='foouser', password='foopassword') + self.assertTrue(J.has_plugin('subversion')) if __name__ == '__main__': unittest.main() diff --git a/jenkinsapi_tests/unittests/test_plugins.py b/jenkinsapi_tests/unittests/test_plugins.py new file mode 100644 index 0000000..2981e2c --- /dev/null +++ b/jenkinsapi_tests/unittests/test_plugins.py @@ -0,0 +1,100 @@ +import mock +import unittest + +from jenkinsapi.jenkins import Jenkins +from jenkinsapi.plugins import Plugins +from jenkinsapi.plugin import Plugin + + +class TestPlugins(unittest.TestCase): + DATA = {'plugins': [ + {'deleted': False, 'hasUpdate': True, 'downgradable': False, + 'dependencies': [{}, {}, {}, {}], + 'longName': 'Jenkins Subversion Plug-in', 'active': True, + 'shortName': 'subversion', 'backupVersion': None, + 'url': 'http://wiki.jenkins-ci.org/display/JENKINS/Subversion+Plugin', + 'enabled': True, 'pinned': False, 'version': '1.45', + 'supportsDynamicLoad': 'MAYBE', 'bundled': True}, + {'deleted': False, 'hasUpdate': True, 'downgradable': False, + 'dependencies': [{}, {}], 'longName': 'Maven Integration plugin', + 'active': True, 'shortName': 'maven-plugin', 'backupVersion': None, + 'url': 'http://wiki.jenkins-ci.org/display/JENKINS/Maven+Project+Plugin', + 'enabled': True, 'pinned': False, 'version': '1.521', + 'supportsDynamicLoad': 'MAYBE', 'bundled': True} + ]} + + @mock.patch.object(Jenkins, '_poll') + def setUp(self, _poll_jenkins): + _poll_jenkins.return_value = {} + + self.J = Jenkins('http://localhost:8080') + + @mock.patch.object(Plugins, '_poll') + def test_get_plugins(self, _poll_plugins): + _poll_plugins.return_value = self.DATA + + # Can we produce a repr string for this object + self.assertIsInstance(self.J.get_plugins(), Plugins) + + @mock.patch.object(Plugins, '_poll') + def test_plugins_len(self, _poll_plugins): + _poll_plugins.return_value = self.DATA + + plugins = self.J.get_plugins() + self.assertEquals(len(plugins), 2) + + @mock.patch.object(Plugins, '_poll') + def test_plugins_contains(self, _poll_plugins): + _poll_plugins.return_value = self.DATA + + plugins = self.J.get_plugins() + self.assertIn('subversion', plugins) + self.assertIn('maven-plugin', plugins) + + @mock.patch.object(Plugins, '_poll') + def test_plugins_values(self, _poll_plugins): + _poll_plugins.return_value = self.DATA + + p = Plugin({'deleted': False, 'hasUpdate': True, 'downgradable': False, + 'dependencies': [{}, {}, {}, {}], + 'longName': 'Jenkins Subversion Plug-in', 'active': True, + 'shortName': 'subversion', 'backupVersion': None, + 'url': 'http://wiki.jenkins-ci.org/display/JENKINS/Subversion+Plugin', + 'enabled': True, 'pinned': False, 'version': '1.45', + 'supportsDynamicLoad': 'MAYBE', 'bundled': True}) + + plugins = self.J.get_plugins().values() + self.assertIn(p, plugins) + + @mock.patch.object(Plugins, '_poll') + def test_plugins_keys(self, _poll_plugins): + _poll_plugins.return_value = self.DATA + + plugins = self.J.get_plugins().keys() + self.assertIn('subversion', plugins) + self.assertIn('maven-plugin', plugins) + + @mock.patch.object(Plugins, '_poll') + def test_plugins_empty(self, _poll_plugins): + _poll_plugins.return_value = {} + + plugins = self.J.get_plugins().keys() + self.assertEquals([], plugins) + + @mock.patch.object(Plugins, '_poll') + def test_plugin_get_by_name(self, _poll_plugins): + _poll_plugins.return_value = self.DATA + + p = Plugin({'deleted': False, 'hasUpdate': True, 'downgradable': False, + 'dependencies': [{}, {}, {}, {}], + 'longName': 'Jenkins Subversion Plug-in', 'active': True, + 'shortName': 'subversion', 'backupVersion': None, + 'url': 'http://wiki.jenkins-ci.org/display/JENKINS/Subversion+Plugin', + 'enabled': True, 'pinned': False, 'version': '1.45', + 'supportsDynamicLoad': 'MAYBE', 'bundled': True}) + + plugin = self.J.get_plugins()['subversion'] + self.assertEquals(p, plugin) + +if __name__ == '__main__': + unittest.main() -- 2.34.1