diff --git a/brewtils/plugin.py b/brewtils/plugin.py index 71f0069a..4b195232 100644 --- a/brewtils/plugin.py +++ b/brewtils/plugin.py @@ -502,25 +502,24 @@ def get_system_matching_version(self, require, **kwargs): req = Requirement(require) require_name = req.name require_version = req.specifier + systems = self._ez_client.find_systems(name=require_name, **kwargs) if require_version: - systems = self._ez_client.find_systems(name=require_name, **kwargs) valid_versions = list( require_version.filter( [str(Version(system.version)) for system in systems] ) ) - if valid_versions: - system_candidates = [ - system for system in systems if system.version in valid_versions - ] - system = system_candidates[0] - for system_candidate in system_candidates: - if Version(system_candidate.version) > Version(system.version): - system = system_candidate else: - system = self._ez_client.find_unique_system( - name=require_name, filter_latest=True, **kwargs - ) + valid_versions = [str(Version(system.version)) for system in systems] + + if valid_versions: + system_candidates = [ + system for system in systems if system.version in valid_versions + ] + system = system_candidates[0] + for system_candidate in system_candidates: + if Version(system_candidate.version) > Version(system.version): + system = system_candidate return system diff --git a/brewtils/test/fixtures.py b/brewtils/test/fixtures.py index 0c84996a..645fc4fe 100644 --- a/brewtils/test/fixtures.py +++ b/brewtils/test/fixtures.py @@ -324,6 +324,16 @@ def bg_system_5(system_dict, bg_instance, bg_command, bg_command_2): return System(**dict_copy) +@pytest.fixture +def bg_system_6(system_dict, bg_instance, bg_command, bg_command_2): + """A system with a different version.""" + dict_copy = copy.deepcopy(system_dict) + dict_copy["version"] = "3.0.0.dev0" + dict_copy["instances"] = [bg_instance] + dict_copy["commands"] = [bg_command, bg_command_2] + return System(**dict_copy) + + @pytest.fixture def child_request_dict(ts_epoch): """A child request represented as a dictionary.""" diff --git a/test/plugin_test.py b/test/plugin_test.py index b10e6e7d..86d65258 100644 --- a/test/plugin_test.py +++ b/test/plugin_test.py @@ -1,8 +1,11 @@ # -*- coding: utf-8 -*- +import copy import logging import logging.config import os import warnings +from packaging.requirements import InvalidRequirement +from packaging.version import InvalidVersion import pytest from mock import ANY, MagicMock, Mock @@ -369,6 +372,7 @@ def test_success( return_value=(admin_processor, request_processor) ) plugin._ez_client.find_unique_system = Mock(return_value=bg_system) + plugin._ez_client.find_systems = Mock(return_value=[bg_system]) plugin._startup() assert admin_processor.startup.called is True @@ -390,6 +394,7 @@ def test_success_no_ns( return_value=(admin_processor, request_processor) ) plugin._ez_client.find_unique_system = Mock(return_value=bg_system) + plugin._ez_client.find_systems = Mock(return_value=[bg_system]) plugin._startup() assert admin_processor.startup.called is True @@ -968,77 +973,77 @@ class TestDependencies(object): # 2.1.0 bg_system_3 # 2.1.1 bg_system_4 # 3.0.0 bg_system_5 - def test_no_specifier( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 - ): - p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_unique_system.return_value = bg_system_5 - # Expect 3.0.0 as latest valid version - # Expect 3.0.0 - assert p.get_system_dependency("system").version == bg_system_5.version - - def test_equals( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 - ): - p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 2.1.1 valid - # Expect 2.1.1 - assert p.get_system_dependency("system==2.1.0").version == bg_system_3.version - - def test_compatible_release( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 - ): - p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 2.1.0, 2.1.1 valid - # Expect 2.1.1 - assert p.get_system_dependency("system~=2.1.0").version == bg_system_4.version - - def test_wildcard_minor( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 - ): + # 3.0.0.dev0 bg_system_6 + @pytest.mark.parametrize( + "latest,versions", + [ + ("1.0.0", ["1.0.0"]), + ("2.0.0", ["1.0.0", "2.0.0"]), + ("1.2.0", ["1.0.0", "1.2.0"]), + ("1.0.0", ["1.0.0", "0.2.1rc1"]), + ("1.0.0rc1", ["1.0.0rc1", "0.2.1"]), + ("1.0.0rc1", ["1.0.0rc1", "0.2.1rc1"]), + ("1.0", ["1.0", "0.2.1"]), + ("1.0.0", ["1.0.0rc1", "1.0.0"]), + ], + ) + def test_determine_latest(client, bg_system, versions, latest): p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 1.0.0, 2.0.0, 2.1.1, 3.0.0 valid - # Expect 3.0.0 - assert p.get_system_dependency("system==2.*").version == bg_system_4.version + system_versions = [] + for version in versions: + s = copy.deepcopy(bg_system) + s.version = version + system_versions.append(s) + p._ez_client.find_systems.return_value = system_versions + assert p.get_system_dependency("system").version == latest - def test_wildcard_patch( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 - ): + @pytest.mark.parametrize( + "latest,versions", + [ + ("b", ["a", "b"]), + ("1.0.0", ["a", "b", "1.0.0"]), + ], + ) + def test_determine_latest_failures(client, bg_system, versions, latest): p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 1.0.0, 2.0.0, 2.1.1, 3.0.0 valid - # Expect 3.0.0 - assert p.get_system_dependency("system==2.1.*").version == bg_system_4.version + system_versions = [] + for version in versions: + s = copy.deepcopy(bg_system) + s.version = version + system_versions.append(s) + p._ez_client.find_systems.return_value = system_versions + with pytest.raises(InvalidVersion): + assert p.get_system_dependency("system").version == latest - def test_excludes( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 + @pytest.mark.parametrize( + "version_spec,latest", + [ + ("system", "3.0.0"), # test no specifier ignores pre-release + ("system==3.0.0.dev", "3.0.0.dev0"), # test version parsing + ("system==2.1.0", "2.1.0"), # test equals + ("system==3", "3.0.0"), # test equals no dev + ("system~=2.1.0", "2.1.1"), # test compatible release + ("system==2.*", "2.1.1"), # test minor wildcard + ("system==2.1.*", "2.1.1"), # test patch wildcard + ("system!=2.1.0", "3.0.0"), # test excludes + ("system>2.1.0", "3.0.0"), # test greater than + ("system>=2.1.0", "3.0.0"), # test greater than or equal + ("system<2.1.0", "2.0.0"), # test less than + ("system<=2.1.0", "2.1.0"), # test less than or equal + ("system<2.0.0,>=1", "1.0.0"), # test range + ("system==2.*,<2.1.1,!=2.1.0", "2.0.0"), # test combination + ], + ) + def test_version_specifier( + plugin, + bg_system, + bg_system_2, + bg_system_3, + bg_system_4, + bg_system_5, + bg_system_6, + version_spec, + latest, ): p = Plugin(bg_host="localhost", system=bg_system) p._ez_client.find_systems.return_value = [ @@ -1047,65 +1052,18 @@ def test_excludes( bg_system_3, bg_system_4, bg_system_5, + bg_system_6, ] - # Expect 1.0.0, 2.0.0, 2.1.1, 3.0.0 valid - # Expect 3.0.0 - assert p.get_system_dependency("system!=2.1.0").version == bg_system_5.version - - def test_gt(plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5): - p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 2.1.1, 3.0.0 valid - # Expect 3.0.0 - assert p.get_system_dependency("system>2.1.0").version == bg_system_5.version - - def test_gte(plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5): - p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 2.1.0, 2.1.1, 3.0.0 valid - # Expect 3.0.0 - assert p.get_system_dependency("system>=2.1.0").version == bg_system_5.version - - def test_lt(plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5): - p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 1.0.0, 2.0.0 valid - # Expect 2.0.0 - assert p.get_system_dependency("system<2.1.0").version == bg_system_2.version - - def test_lte(plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5): - p = Plugin(bg_host="localhost", system=bg_system) - p._ez_client.find_systems.return_value = [ - bg_system, - bg_system_2, - bg_system_3, - bg_system_4, - bg_system_5, - ] - # Expect 1.0.0, 2.0.0, 2.1.0 valid - # Expect 2.1.0 - assert p.get_system_dependency("system<=2.1.0").version == bg_system_3.version - - def test_range( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 + assert p.get_system_dependency(version_spec).version == latest + + def test_no_match( + plugin, + bg_system, + bg_system_2, + bg_system_3, + bg_system_4, + bg_system_5, + bg_system_6, ): p = Plugin(bg_host="localhost", system=bg_system) p._ez_client.find_systems.return_value = [ @@ -1114,13 +1072,29 @@ def test_range( bg_system_3, bg_system_4, bg_system_5, + bg_system_6, ] - # Expect 1.0.0 valid - # Expect 1.0.0 - assert p.get_system_dependency("system<2.0.0,>=1").version == bg_system.version + p._wait = Mock(return_value=None) + with pytest.raises(PluginValidationError): + assert p.get_system_dependency("system==3.0.1.dev0").version - def test_combo( - plugin, bg_system, bg_system_2, bg_system_3, bg_system_4, bg_system_5 + @pytest.mark.parametrize( + "version_spec", + [ + "system==*", + "system==a", + "system$$3.0.0", + ], + ) + def test_invalid_requirement( + plugin, + bg_system, + bg_system_2, + bg_system_3, + bg_system_4, + bg_system_5, + bg_system_6, + version_spec, ): p = Plugin(bg_host="localhost", system=bg_system) p._ez_client.find_systems.return_value = [ @@ -1129,10 +1103,7 @@ def test_combo( bg_system_3, bg_system_4, bg_system_5, + bg_system_6, ] - # Expect 1.0.0 valid - # Expect 1.0.0 - assert ( - p.get_system_dependency("system==2.*,<2.1.1,!=2.1.0").version - == bg_system_2.version - ) + with pytest.raises(InvalidRequirement): + p.get_system_dependency(version_spec)