Merge "Provider helper classes for plugin data management"
This commit is contained in:
commit
344b5f3ffa
|
@ -6,3 +6,8 @@ API reference
|
||||||
.. automodule:: jenkins
|
.. automodule:: jenkins
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
|
|
||||||
|
.. automodule:: jenkins.plugins
|
||||||
|
:members:
|
||||||
|
:noindex:
|
||||||
|
:undoc-members:
|
||||||
|
|
|
@ -54,6 +54,7 @@ import sys
|
||||||
import time
|
import time
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
import multi_key_dict
|
||||||
import six
|
import six
|
||||||
from six.moves.http_client import BadStatusLine
|
from six.moves.http_client import BadStatusLine
|
||||||
from six.moves.urllib.error import HTTPError
|
from six.moves.urllib.error import HTTPError
|
||||||
|
@ -61,6 +62,10 @@ from six.moves.urllib.error import URLError
|
||||||
from six.moves.urllib.parse import quote, urlencode, urljoin, urlparse
|
from six.moves.urllib.parse import quote, urlencode, urljoin, urlparse
|
||||||
from six.moves.urllib.request import Request, urlopen
|
from six.moves.urllib.request import Request, urlopen
|
||||||
|
|
||||||
|
from jenkins import plugins
|
||||||
|
|
||||||
|
warnings.simplefilter("default", DeprecationWarning)
|
||||||
|
|
||||||
if sys.version_info < (2, 7, 0):
|
if sys.version_info < (2, 7, 0):
|
||||||
warnings.warn("Support for python 2.6 is deprecated and will be removed.")
|
warnings.warn("Support for python 2.6 is deprecated and will be removed.")
|
||||||
|
|
||||||
|
@ -497,7 +502,10 @@ class Jenkins(object):
|
||||||
"""Get all installed plugins information on this Master.
|
"""Get all installed plugins information on this Master.
|
||||||
|
|
||||||
This method retrieves information about each plugin that is installed
|
This method retrieves information about each plugin that is installed
|
||||||
on master.
|
on master returning the raw plugin data in a JSON format.
|
||||||
|
|
||||||
|
.. deprecated:: 0.4.9
|
||||||
|
Use :func:`get_plugins` instead.
|
||||||
|
|
||||||
:param depth: JSON depth, ``int``
|
:param depth: JSON depth, ``int``
|
||||||
:returns: info on all plugins ``[dict]``
|
:returns: info on all plugins ``[dict]``
|
||||||
|
@ -515,24 +523,24 @@ class Jenkins(object):
|
||||||
u'gearman-plugin', u'bundled': False}, ..]
|
u'gearman-plugin', u'bundled': False}, ..]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
warnings.warn("get_plugins_info() is deprecated, use get_plugins()",
|
||||||
plugins_info = json.loads(self.jenkins_open(
|
DeprecationWarning)
|
||||||
Request(self._build_url(PLUGIN_INFO, locals()))
|
return [plugin_data for plugin_data in self.get_plugins(depth).values()]
|
||||||
))
|
|
||||||
return plugins_info['plugins']
|
|
||||||
except (HTTPError, BadStatusLine):
|
|
||||||
raise BadHTTPException("Error communicating with server[%s]"
|
|
||||||
% self.server)
|
|
||||||
except ValueError:
|
|
||||||
raise JenkinsException("Could not parse JSON info for server[%s]"
|
|
||||||
% self.server)
|
|
||||||
|
|
||||||
def get_plugin_info(self, name, depth=2):
|
def get_plugin_info(self, name, depth=2):
|
||||||
"""Get an installed plugin information on this Master.
|
"""Get an installed plugin information on this Master.
|
||||||
|
|
||||||
This method retrieves information about a speicifc plugin.
|
This method retrieves information about a specific plugin and returns
|
||||||
|
the raw plugin data in a JSON format.
|
||||||
The passed in plugin name (short or long) must be an exact match.
|
The passed in plugin name (short or long) must be an exact match.
|
||||||
|
|
||||||
|
.. note:: Calling this method will query Jenkins fresh for the
|
||||||
|
information for all plugins on each call. If you need to retrieve
|
||||||
|
information for multiple plugins it's recommended to use
|
||||||
|
:func:`get_plugins` instead, which will return a multi key
|
||||||
|
dictionary that can be accessed via either the short or long name
|
||||||
|
of the plugin.
|
||||||
|
|
||||||
:param name: Name (short or long) of plugin, ``str``
|
:param name: Name (short or long) of plugin, ``str``
|
||||||
:param depth: JSON depth, ``int``
|
:param depth: JSON depth, ``int``
|
||||||
:returns: a specific plugin ``dict``
|
:returns: a specific plugin ``dict``
|
||||||
|
@ -550,12 +558,45 @@ class Jenkins(object):
|
||||||
u'gearman-plugin', u'bundled': False}
|
u'gearman-plugin', u'bundled': False}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
plugins_info = self.get_plugins(depth)
|
||||||
try:
|
try:
|
||||||
plugins_info = json.loads(self.jenkins_open(
|
return plugins_info[name]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_plugins(self, depth=2):
|
||||||
|
"""Return plugins info using helper class for version comparison
|
||||||
|
|
||||||
|
This method retrieves information about all the installed plugins and
|
||||||
|
uses a Plugin helper class to simplify version comparison. Also uses
|
||||||
|
a multi key dict to allow retrieval via either short or long names.
|
||||||
|
|
||||||
|
When printing/dumping the data, the version will transparently return
|
||||||
|
a unicode string, which is exactly what was previously returned by the
|
||||||
|
API.
|
||||||
|
|
||||||
|
:param depth: JSON depth, ``int``
|
||||||
|
:returns: info on all plugins ``[dict]``
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
>>> j = Jenkins()
|
||||||
|
>>> info = j.get_plugins()
|
||||||
|
>>> print(info)
|
||||||
|
{('gearman-plugin', 'Gearman Plugin'):
|
||||||
|
{u'backupVersion': None, u'version': u'0.0.4',
|
||||||
|
u'deleted': False, u'supportsDynamicLoad': u'MAYBE',
|
||||||
|
u'hasUpdate': True, u'enabled': True, u'pinned': False,
|
||||||
|
u'downgradable': False, u'dependencies': [], u'url':
|
||||||
|
u'http://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin',
|
||||||
|
u'longName': u'Gearman Plugin', u'active': True, u'shortName':
|
||||||
|
u'gearman-plugin', u'bundled': False}, ...}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
plugins_info_json = json.loads(self.jenkins_open(
|
||||||
Request(self._build_url(PLUGIN_INFO, locals()))))
|
Request(self._build_url(PLUGIN_INFO, locals()))))
|
||||||
for plugin in plugins_info['plugins']:
|
|
||||||
if plugin['longName'] == name or plugin['shortName'] == name:
|
|
||||||
return plugin
|
|
||||||
except (HTTPError, BadStatusLine):
|
except (HTTPError, BadStatusLine):
|
||||||
raise BadHTTPException("Error communicating with server[%s]"
|
raise BadHTTPException("Error communicating with server[%s]"
|
||||||
% self.server)
|
% self.server)
|
||||||
|
@ -563,6 +604,13 @@ class Jenkins(object):
|
||||||
raise JenkinsException("Could not parse JSON info for server[%s]"
|
raise JenkinsException("Could not parse JSON info for server[%s]"
|
||||||
% self.server)
|
% self.server)
|
||||||
|
|
||||||
|
plugins_data = multi_key_dict.multi_key_dict()
|
||||||
|
for plugin_data in plugins_info_json['plugins']:
|
||||||
|
keys = (str(plugin_data['shortName']), str(plugin_data['longName']))
|
||||||
|
plugins_data[keys] = plugins.Plugin(**plugin_data)
|
||||||
|
|
||||||
|
return plugins_data
|
||||||
|
|
||||||
def get_jobs(self, folder_depth=0):
|
def get_jobs(self, folder_depth=0):
|
||||||
"""Get list of jobs.
|
"""Get list of jobs.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
# Software License Agreement (BSD License)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following
|
||||||
|
# disclaimer in the documentation and/or other materials provided
|
||||||
|
# with the distribution.
|
||||||
|
# * Neither the name of Willow Garage, Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Darragh Bailey <dbailey@hp.com>
|
||||||
|
|
||||||
|
'''
|
||||||
|
.. module:: jenkins.plugins
|
||||||
|
:platform: Unix, Windows
|
||||||
|
:synopsis: Class for interacting with plugins
|
||||||
|
'''
|
||||||
|
|
||||||
|
import operator
|
||||||
|
import re
|
||||||
|
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(dict):
|
||||||
|
'''Dictionary object containing plugin metadata.'''
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
'''Populates dictionary using json object input.
|
||||||
|
|
||||||
|
accepts same arguments as python `dict` class.
|
||||||
|
'''
|
||||||
|
version = kwargs.pop('version', None)
|
||||||
|
|
||||||
|
super(Plugin, self).__init__(*args, **kwargs)
|
||||||
|
self['version'] = version
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
'''Overrides default setter to ensure that the version key is always
|
||||||
|
a PluginVersion class to abstract and simplify version comparisons
|
||||||
|
'''
|
||||||
|
if key == 'version':
|
||||||
|
value = PluginVersion(value)
|
||||||
|
super(Plugin, self).__setitem__(key, value)
|
||||||
|
|
||||||
|
|
||||||
|
class PluginVersion(object):
|
||||||
|
'''Class providing comparison capabilities for plugin versions.'''
|
||||||
|
|
||||||
|
_VERSION_RE = re.compile(r'(.*)-(?:SNAPSHOT|BETA)')
|
||||||
|
|
||||||
|
def __init__(self, version):
|
||||||
|
'''Parse plugin version and store it for comparison.'''
|
||||||
|
|
||||||
|
self._version = version
|
||||||
|
self.parsed_version = pkg_resources.parse_version(
|
||||||
|
self.__convert_version(version))
|
||||||
|
|
||||||
|
def __convert_version(self, version):
|
||||||
|
return self._VERSION_RE.sub(r'\g<1>.preview', str(version))
|
||||||
|
|
||||||
|
def __compare(self, op, version):
|
||||||
|
return op(self.parsed_version, pkg_resources.parse_version(
|
||||||
|
self.__convert_version(version)))
|
||||||
|
|
||||||
|
def __le__(self, version):
|
||||||
|
return self.__compare(operator.le, version)
|
||||||
|
|
||||||
|
def __lt__(self, version):
|
||||||
|
return self.__compare(operator.lt, version)
|
||||||
|
|
||||||
|
def __ge__(self, version):
|
||||||
|
return self.__compare(operator.ge, version)
|
||||||
|
|
||||||
|
def __gt__(self, version):
|
||||||
|
return self.__compare(operator.gt, version)
|
||||||
|
|
||||||
|
def __eq__(self, version):
|
||||||
|
return self.__compare(operator.eq, version)
|
||||||
|
|
||||||
|
def __ne__(self, version):
|
||||||
|
return self.__compare(operator.ne, version)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self._version)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self._version)
|
|
@ -1,2 +1,3 @@
|
||||||
six>=1.3.0
|
six>=1.3.0
|
||||||
pbr>=0.8.2,<2.0
|
pbr>=0.8.2,<2.0
|
||||||
|
multi_key_dict
|
||||||
|
|
|
@ -6,4 +6,5 @@ unittest2
|
||||||
python-subunit
|
python-subunit
|
||||||
sphinx>=1.2,<1.3.0
|
sphinx>=1.2,<1.3.0
|
||||||
testrepository
|
testrepository
|
||||||
|
testscenarios
|
||||||
testtools
|
testtools
|
||||||
|
|
|
@ -1,7 +1,42 @@
|
||||||
|
# Software License Agreement (BSD License)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following
|
||||||
|
# disclaimer in the documentation and/or other materials provided
|
||||||
|
# with the distribution.
|
||||||
|
# * Neither the name of Willow Garage, Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from mock import patch
|
from mock import patch
|
||||||
|
from testscenarios.testcase import TestWithScenarios
|
||||||
|
|
||||||
import jenkins
|
import jenkins
|
||||||
|
from jenkins import plugins
|
||||||
from tests.base import JenkinsTestBase
|
from tests.base import JenkinsTestBase
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +64,14 @@ class JenkinsPluginsBase(JenkinsTestBase):
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updated_plugin_info_json = {
|
||||||
|
u"plugins":
|
||||||
|
[
|
||||||
|
dict(plugin_info_json[u"plugins"][0],
|
||||||
|
**{u"version": u"1.6"})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class JenkinsPluginsInfoTest(JenkinsPluginsBase):
|
class JenkinsPluginsInfoTest(JenkinsPluginsBase):
|
||||||
|
|
||||||
|
@ -129,6 +172,28 @@ class JenkinsPluginInfoTest(JenkinsPluginsBase):
|
||||||
self.assertEqual(plugin_info, self.plugin_info_json['plugins'][0])
|
self.assertEqual(plugin_info, self.plugin_info_json['plugins'][0])
|
||||||
self._check_requests(jenkins_mock.call_args_list)
|
self._check_requests(jenkins_mock.call_args_list)
|
||||||
|
|
||||||
|
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
||||||
|
def test_get_plugin_info_updated(self, jenkins_mock):
|
||||||
|
|
||||||
|
jenkins_mock.side_effect = [
|
||||||
|
json.dumps(self.plugin_info_json),
|
||||||
|
json.dumps(self.updated_plugin_info_json)
|
||||||
|
]
|
||||||
|
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
|
||||||
|
|
||||||
|
plugins_info = j.get_plugins()
|
||||||
|
self.assertEqual(plugins_info["mailer"]["version"],
|
||||||
|
self.plugin_info_json['plugins'][0]["version"])
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
plugins_info["mailer"]["version"],
|
||||||
|
self.updated_plugin_info_json['plugins'][0]["version"])
|
||||||
|
|
||||||
|
plugins_info = j.get_plugins()
|
||||||
|
self.assertEqual(
|
||||||
|
plugins_info["mailer"]["version"],
|
||||||
|
self.updated_plugin_info_json['plugins'][0]["version"])
|
||||||
|
|
||||||
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
@patch.object(jenkins.Jenkins, 'jenkins_open')
|
||||||
def test_return_none(self, jenkins_mock):
|
def test_return_none(self, jenkins_mock):
|
||||||
jenkins_mock.return_value = json.dumps(self.plugin_info_json)
|
jenkins_mock.return_value = json.dumps(self.plugin_info_json)
|
||||||
|
@ -191,3 +256,87 @@ class JenkinsPluginInfoTest(JenkinsPluginsBase):
|
||||||
str(context_manager.exception),
|
str(context_manager.exception),
|
||||||
'Error communicating with server[http://example.com/]')
|
'Error communicating with server[http://example.com/]')
|
||||||
self._check_requests(jenkins_mock.call_args_list)
|
self._check_requests(jenkins_mock.call_args_list)
|
||||||
|
|
||||||
|
|
||||||
|
class PluginsTestScenarios(TestWithScenarios, JenkinsPluginsBase):
|
||||||
|
scenarios = [
|
||||||
|
('s1', dict(v1='1.0.0', op='__gt__', v2='0.8.0')),
|
||||||
|
('s2', dict(v1='1.0.1alpha', op='__gt__', v2='1.0.0')),
|
||||||
|
('s3', dict(v1='1.0', op='__eq__', v2='1.0.0')),
|
||||||
|
('s4', dict(v1='1.0', op='__eq__', v2='1.0')),
|
||||||
|
('s5', dict(v1='1.0', op='__lt__', v2='1.8.0')),
|
||||||
|
('s6', dict(v1='1.0.1alpha', op='__lt__', v2='1.0.1')),
|
||||||
|
('s7', dict(v1='1.0alpha', op='__lt__', v2='1.0.0')),
|
||||||
|
('s8', dict(v1='1.0-alpha', op='__lt__', v2='1.0.0')),
|
||||||
|
('s9', dict(v1='1.1-alpha', op='__gt__', v2='1.0')),
|
||||||
|
('s10', dict(v1='1.0-SNAPSHOT', op='__lt__', v2='1.0')),
|
||||||
|
('s11', dict(v1='1.0.preview', op='__lt__', v2='1.0')),
|
||||||
|
('s12', dict(v1='1.1-SNAPSHOT', op='__gt__', v2='1.0')),
|
||||||
|
('s13', dict(v1='1.0a-SNAPSHOT', op='__lt__', v2='1.0a')),
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(PluginsTestScenarios, self).setUp()
|
||||||
|
|
||||||
|
plugin_info_json = dict(self.plugin_info_json)
|
||||||
|
plugin_info_json[u"plugins"][0][u"version"] = self.v1
|
||||||
|
|
||||||
|
patcher = patch.object(jenkins.Jenkins, 'jenkins_open')
|
||||||
|
self.jenkins_mock = patcher.start()
|
||||||
|
self.addCleanup(patcher.stop)
|
||||||
|
self.jenkins_mock.return_value = json.dumps(plugin_info_json)
|
||||||
|
|
||||||
|
def test_plugin_version_comparison(self):
|
||||||
|
"""Verify that valid versions are ordinally correct.
|
||||||
|
|
||||||
|
That is, for each given scenario, v1.op(v2)==True where 'op' is the
|
||||||
|
equality operator defined for the scenario.
|
||||||
|
"""
|
||||||
|
plugin_name = "Jenkins Mailer Plugin"
|
||||||
|
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
|
||||||
|
plugin_info = j.get_plugins()[plugin_name]
|
||||||
|
v1 = plugin_info.get("version")
|
||||||
|
|
||||||
|
op = getattr(v1, self.op)
|
||||||
|
|
||||||
|
self.assertTrue(op(self.v2),
|
||||||
|
msg="Unexpectedly found {0} {2} {1} == False "
|
||||||
|
"when comparing versions!"
|
||||||
|
.format(v1, self.v2, self.op))
|
||||||
|
|
||||||
|
def test_plugin_version_object_comparison(self):
|
||||||
|
"""Verify use of PluginVersion for comparison
|
||||||
|
|
||||||
|
Verify that converting the version to be compared to the same object
|
||||||
|
type of PluginVersion before comparing provides the same result.
|
||||||
|
"""
|
||||||
|
plugin_name = "Jenkins Mailer Plugin"
|
||||||
|
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
|
||||||
|
plugin_info = j.get_plugins()[plugin_name]
|
||||||
|
v1 = plugin_info.get("version")
|
||||||
|
|
||||||
|
op = getattr(v1, self.op)
|
||||||
|
v2 = plugins.PluginVersion(self.v2)
|
||||||
|
|
||||||
|
self.assertTrue(op(v2),
|
||||||
|
msg="Unexpectedly found {0} {2} {1} == False "
|
||||||
|
"when comparing versions!"
|
||||||
|
.format(v1, v2, self.op))
|
||||||
|
|
||||||
|
|
||||||
|
class PluginsTest(JenkinsPluginsBase):
|
||||||
|
|
||||||
|
def test_plugin_equal(self):
|
||||||
|
|
||||||
|
p1 = plugins.Plugin(self.plugin_info_json)
|
||||||
|
p2 = plugins.Plugin(self.plugin_info_json)
|
||||||
|
|
||||||
|
self.assertEqual(p1, p2)
|
||||||
|
|
||||||
|
def test_plugin_not_equal(self):
|
||||||
|
|
||||||
|
p1 = plugins.Plugin(self.plugin_info_json)
|
||||||
|
p2 = plugins.Plugin(self.plugin_info_json)
|
||||||
|
p2[u'version'] = u"1.6"
|
||||||
|
|
||||||
|
self.assertNotEqual(p1, p2)
|
||||||
|
|
Loading…
Reference in New Issue