| |
@@ -0,0 +1,532 @@
|
| |
+ import logging
|
| |
+ from unittest.mock import call, MagicMock, Mock, patch
|
| |
+
|
| |
+ import beanbag
|
| |
+ import fedora_messaging.api
|
| |
+ import koji
|
| |
+ import pytest
|
| |
+
|
| |
+ import toddlers.plugins.pdc_modules as pdc_modules
|
| |
+
|
| |
+
|
| |
+ class TestPDCModulesToddler:
|
| |
+
|
| |
+ toddler_cls = pdc_modules.PDCModules
|
| |
+
|
| |
+ def test_accepts_topic_invalid(self, toddler):
|
| |
+ assert toddler.accepts_topic("foo.bar") is False
|
| |
+
|
| |
+ @pytest.mark.parametrize(
|
| |
+ "topic",
|
| |
+ [
|
| |
+ "org.fedoraproject.*.mbs.module.state.change",
|
| |
+ "org.fedoraproject.stg.mbs.module.state.change",
|
| |
+ "org.fedoraproject.prod.mbs.module.state.change",
|
| |
+ ],
|
| |
+ )
|
| |
+ def test_accepts_topic_valid(self, topic, toddler):
|
| |
+ assert toddler.accepts_topic(topic)
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_pdc_api_exception(self, pdc, toddler):
|
| |
+ """
|
| |
+ Assert that exception is raised when pdc_api can't be retrieved.
|
| |
+ """
|
| |
+ client = MagicMock()
|
| |
+
|
| |
+ res = Mock()
|
| |
+ res.status_code = 500
|
| |
+
|
| |
+ client["modules"]._.side_effect = beanbag.BeanBagException(res, "")
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {}
|
| |
+
|
| |
+ with pytest.raises(beanbag.BeanBagException) as e:
|
| |
+ toddler.process({"config": "foobar"}, msg)
|
| |
+ assert e.status_code == 500
|
| |
+
|
| |
+ client["modules"]._.assert_called_with(page_size=1)
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_invalid_state(self, pdc, caplog, toddler):
|
| |
+ caplog.set_level(logging.INFO)
|
| |
+ client = MagicMock()
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {"state_name": "invalid"}
|
| |
+
|
| |
+ toddler.process({"config": "foobar"}, msg)
|
| |
+
|
| |
+ client["modules"]._.assert_called_with(page_size=1)
|
| |
+
|
| |
+ assert len(caplog.records) == 1
|
| |
+ assert (
|
| |
+ caplog.records[-1].message
|
| |
+ == "We are not interested in this state: 'invalid', skip"
|
| |
+ )
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_existing_module_build(self, pdc, toddler):
|
| |
+ """
|
| |
+ Assert that the PDC is correctly updated when state is changed to build.
|
| |
+ """
|
| |
+ client = MagicMock()
|
| |
+ pdc_api = "modules"
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {
|
| |
+ "state_name": "build",
|
| |
+ "name": "module",
|
| |
+ "stream": 6,
|
| |
+ "version": 6.1,
|
| |
+ "koji_tag": "tag",
|
| |
+ }
|
| |
+ uid = "module:6:6.1:00000000"
|
| |
+
|
| |
+ toddler.process({"config": "foobar"}, msg)
|
| |
+
|
| |
+ print(client[pdc_api]._.mock_calls)
|
| |
+
|
| |
+ assert call(page_size=1) in client[pdc_api]._.mock_calls
|
| |
+ assert call(page_size=-1, uid=uid) in client[pdc_api]._.mock_calls
|
| |
+
|
| |
+ assert client[pdc_api][123].mock_calls == [call._.__iadd__({"koji_tag": "tag"})]
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.koji")
|
| |
+ @patch("toddlers.plugins.pdc_modules.Modulemd")
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_existing_module_ready(self, pdc, modulemd, koji, toddler):
|
| |
+ """
|
| |
+ Assert that the PDC is correctly updated when state is changed to ready.
|
| |
+ """
|
| |
+ client = MagicMock()
|
| |
+ pdc_api = "modules"
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ mmd = Mock()
|
| |
+
|
| |
+ modulemd.Module.new_from_string.return_value = mmd
|
| |
+
|
| |
+ session = Mock()
|
| |
+ session.listTaggedRPMS.return_value = (
|
| |
+ [
|
| |
+ {
|
| |
+ "build_id": 123,
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "x86_64",
|
| |
+ }
|
| |
+ ],
|
| |
+ [{"build_id": 123, "name": "rpm", "nvr": "rpm-1.0-1"}],
|
| |
+ )
|
| |
+ koji.ClientSession.return_value = session
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {
|
| |
+ "state_name": "ready",
|
| |
+ "name": "module",
|
| |
+ "stream": 6,
|
| |
+ "version": 6.1,
|
| |
+ }
|
| |
+ uid = "module:6:6.1:00000000"
|
| |
+
|
| |
+ config = {"koji_url": "url"}
|
| |
+
|
| |
+ toddler.process(config, msg)
|
| |
+
|
| |
+ assert call(page_size=1) in client[pdc_api]._.mock_calls
|
| |
+ assert call(page_size=-1, uid=uid) in client[pdc_api]._.mock_calls
|
| |
+
|
| |
+ assert client[pdc_api][123].mock_calls == [
|
| |
+ call._.__iadd__(
|
| |
+ {
|
| |
+ "active": True,
|
| |
+ "rpms": [
|
| |
+ {
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "x86_64",
|
| |
+ "srpm_name": "rpm",
|
| |
+ "srpm_nevra": "rpm-1.0-1",
|
| |
+ }
|
| |
+ ],
|
| |
+ }
|
| |
+ )
|
| |
+ ]
|
| |
+
|
| |
+ assert mmd.upgrade.call_count == 1
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.koji")
|
| |
+ @patch("toddlers.plugins.pdc_modules.Modulemd")
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_existing_module_ready_src_arch(self, pdc, modulemd, koji, toddler):
|
| |
+ """
|
| |
+ Assert that the PDC is correctly updated when state is changed to ready and the module has
|
| |
+ src arch.
|
| |
+ """
|
| |
+ client = MagicMock()
|
| |
+ pdc_api = "modules"
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ mmd_rpm = Mock()
|
| |
+ mmd_rpm.get_ref.return_value = "foo"
|
| |
+
|
| |
+ mmd = Mock()
|
| |
+ mmd.get_rpm_components.return_value = {"rpm": mmd_rpm}
|
| |
+ mmd.get_xmd.return_value = {"mbs": {"rpms": {"rpm": {"ref": "bar"}}}}
|
| |
+
|
| |
+ modulemd.Module.new_from_string.return_value = mmd
|
| |
+
|
| |
+ session = Mock()
|
| |
+ session.listTaggedRPMS.return_value = (
|
| |
+ [
|
| |
+ {
|
| |
+ "build_id": 123,
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "src",
|
| |
+ }
|
| |
+ ],
|
| |
+ [{"build_id": 123, "name": "rpm", "nvr": "rpm-1.0-1"}],
|
| |
+ )
|
| |
+ koji.ClientSession.return_value = session
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {
|
| |
+ "state_name": "ready",
|
| |
+ "name": "module",
|
| |
+ "stream": 6,
|
| |
+ "version": 6.1,
|
| |
+ }
|
| |
+ uid = "module:6:6.1:00000000"
|
| |
+
|
| |
+ config = {"koji_url": "url"}
|
| |
+
|
| |
+ toddler.process(config, msg)
|
| |
+
|
| |
+ assert call(page_size=1) in client[pdc_api]._.mock_calls
|
| |
+ assert call(page_size=-1, uid=uid) in client[pdc_api]._.mock_calls
|
| |
+
|
| |
+ assert client[pdc_api][123].mock_calls == [
|
| |
+ call._.__iadd__(
|
| |
+ {
|
| |
+ "active": True,
|
| |
+ "rpms": [
|
| |
+ {
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "src",
|
| |
+ "srpm_name": "rpm",
|
| |
+ "srpm_commit_hash": "bar",
|
| |
+ "srpm_commit_branch": "foo",
|
| |
+ }
|
| |
+ ],
|
| |
+ }
|
| |
+ )
|
| |
+ ]
|
| |
+
|
| |
+ assert mmd.upgrade.call_count == 1
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.koji.ClientSession")
|
| |
+ @patch("toddlers.plugins.pdc_modules.Modulemd")
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_existing_module_ready_koji_error(
|
| |
+ self, pdc, modulemd, koji_client, toddler
|
| |
+ ):
|
| |
+ """
|
| |
+ Assert that the PDC is correctly updated when state is changed to ready and koji error
|
| |
+ is encountered.
|
| |
+ """
|
| |
+ client = MagicMock()
|
| |
+ pdc_api = "modules"
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ mmd = Mock()
|
| |
+
|
| |
+ modulemd.Module.new_from_string.return_value = mmd
|
| |
+
|
| |
+ session = Mock()
|
| |
+ session.listTaggedRPMS.side_effect = koji.AuthError()
|
| |
+ koji_client.return_value = session
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {
|
| |
+ "state_name": "ready",
|
| |
+ "name": "module",
|
| |
+ "stream": 6,
|
| |
+ "version": 6.1,
|
| |
+ }
|
| |
+ uid = "module:6:6.1:00000000"
|
| |
+
|
| |
+ config = {"koji_url": "url"}
|
| |
+
|
| |
+ toddler.process(config, msg)
|
| |
+
|
| |
+ assert call(page_size=1) in client[pdc_api]._.mock_calls
|
| |
+ assert call(page_size=-1, uid=uid) in client[pdc_api]._.mock_calls
|
| |
+
|
| |
+ assert client[pdc_api][123].mock_calls == [
|
| |
+ call._.__iadd__({"active": True, "rpms": []})
|
| |
+ ]
|
| |
+
|
| |
+ assert mmd.upgrade.call_count == 1
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.koji")
|
| |
+ @patch("toddlers.plugins.pdc_modules.Modulemd")
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_new_module_ready(self, pdc, modulemd, koji, toddler):
|
| |
+ """
|
| |
+ Assert that the PDC is correctly updated when state is changed and module doesn't exist.
|
| |
+ """
|
| |
+ client = MagicMock()
|
| |
+ pdc_api = "modules"
|
| |
+ uid = "module:6:6.1:00000000"
|
| |
+ client[pdc_api]._.side_effect = (
|
| |
+ "",
|
| |
+ [],
|
| |
+ {"uid": uid, "modulemd": "module", "koji_tag": "NA"},
|
| |
+ )
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ deps = Mock()
|
| |
+ stream = Mock()
|
| |
+ stream.get.return_value = ["stream"]
|
| |
+ deps.get_requires.return_value = {
|
| |
+ "dependency": stream,
|
| |
+ }
|
| |
+ deps.get_buildrequires.return_value = {
|
| |
+ "dependency": stream,
|
| |
+ }
|
| |
+
|
| |
+ mmd = Mock()
|
| |
+ mmd.get_dependencies.return_value = [deps]
|
| |
+
|
| |
+ modulemd.Module.new_from_string.return_value = mmd
|
| |
+
|
| |
+ session = Mock()
|
| |
+ session.listTaggedRPMS.return_value = (
|
| |
+ [
|
| |
+ {
|
| |
+ "build_id": 123,
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "x86_64",
|
| |
+ }
|
| |
+ ],
|
| |
+ [{"build_id": 123, "name": "rpm", "nvr": "rpm-1.0-1"}],
|
| |
+ )
|
| |
+ koji.ClientSession.return_value = session
|
| |
+
|
| |
+ req = Mock()
|
| |
+ resp_mbs_module = Mock()
|
| |
+ resp_mbs_module.json.return_value = {
|
| |
+ "modulemd": "module",
|
| |
+ }
|
| |
+ req.get.return_value = resp_mbs_module
|
| |
+ toddler.requests_session = req
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {
|
| |
+ "id": 123,
|
| |
+ "state_name": "ready",
|
| |
+ "name": "module",
|
| |
+ "stream": 6,
|
| |
+ "version": 6.1,
|
| |
+ }
|
| |
+
|
| |
+ config = {"koji_url": "koji_url", "mbs_url": "mbs_url"}
|
| |
+
|
| |
+ toddler.process(config, msg)
|
| |
+
|
| |
+ resp_mbs_module.raise_for_status.assert_called_once()
|
| |
+ req.get.assert_called_with("mbs_url/123?verbose=True", timeout=30)
|
| |
+
|
| |
+ assert client[pdc_api]._.mock_calls == [
|
| |
+ call(page_size=1),
|
| |
+ call(page_size=-1, uid=uid),
|
| |
+ call(
|
| |
+ {
|
| |
+ "name": "module",
|
| |
+ "stream": 6,
|
| |
+ "version": 6.1,
|
| |
+ "context": "00000000",
|
| |
+ "koji_tag": "NA",
|
| |
+ "runtime_deps": [{"dependency": "dependency", "stream": "stream"}],
|
| |
+ "build_deps": [{"dependency": "dependency", "stream": "stream"}],
|
| |
+ "modulemd": "module",
|
| |
+ }
|
| |
+ ),
|
| |
+ ]
|
| |
+
|
| |
+ assert client[pdc_api][123].mock_calls == [
|
| |
+ call._.__iadd__(
|
| |
+ {
|
| |
+ "active": True,
|
| |
+ "rpms": [
|
| |
+ {
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "x86_64",
|
| |
+ "srpm_name": "rpm",
|
| |
+ "srpm_nevra": "rpm-1.0-1",
|
| |
+ }
|
| |
+ ],
|
| |
+ }
|
| |
+ )
|
| |
+ ]
|
| |
+
|
| |
+ assert mmd.upgrade.call_count == 2
|
| |
+
|
| |
+ @patch("toddlers.plugins.pdc_modules.koji")
|
| |
+ @patch("toddlers.plugins.pdc_modules.Modulemd")
|
| |
+ @patch("toddlers.plugins.pdc_modules.pdc_client_for_config")
|
| |
+ def test_process_new_module_ready_different_pdc_api(
|
| |
+ self, pdc, modulemd, koji, toddler
|
| |
+ ):
|
| |
+ """
|
| |
+ Assert that the PDC is correctly updated when state is changed, module doesn't exist and
|
| |
+ different pdc_api "unreleasedvariants" is used.
|
| |
+ """
|
| |
+ client = MagicMock()
|
| |
+ pdc_api = "unreleasedvariants"
|
| |
+
|
| |
+ res = Mock()
|
| |
+ res.status_code = 404
|
| |
+
|
| |
+ uid = "module:6:6.1"
|
| |
+ module_mock = MagicMock()
|
| |
+ module_mock._.side_effect = (
|
| |
+ beanbag.BeanBagException(res, ""),
|
| |
+ [],
|
| |
+ {"variant_uid": uid, "modulemd": "module", "koji_tag": "NA"},
|
| |
+ )
|
| |
+
|
| |
+ client.__getitem__.return_value = module_mock
|
| |
+ pdc.return_value = client
|
| |
+
|
| |
+ deps = Mock()
|
| |
+ stream = Mock()
|
| |
+ stream.get.return_value = ["stream"]
|
| |
+ deps.get_requires.return_value = {
|
| |
+ "dependency": stream,
|
| |
+ }
|
| |
+ deps.get_buildrequires.return_value = {
|
| |
+ "dependency": stream,
|
| |
+ }
|
| |
+
|
| |
+ mmd = Mock()
|
| |
+ mmd.get_dependencies.return_value = [deps]
|
| |
+
|
| |
+ modulemd.Module.new_from_string.return_value = mmd
|
| |
+
|
| |
+ session = Mock()
|
| |
+ session.listTaggedRPMS.return_value = (
|
| |
+ [
|
| |
+ {
|
| |
+ "build_id": 123,
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "x86_64",
|
| |
+ }
|
| |
+ ],
|
| |
+ [{"build_id": 123, "name": "rpm", "nvr": "rpm-1.0-1"}],
|
| |
+ )
|
| |
+ koji.ClientSession.return_value = session
|
| |
+
|
| |
+ req = Mock()
|
| |
+ resp_mbs_module = Mock()
|
| |
+ resp_mbs_module.json.return_value = {
|
| |
+ "modulemd": "module",
|
| |
+ }
|
| |
+ req.get.return_value = resp_mbs_module
|
| |
+ toddler.requests_session = req
|
| |
+
|
| |
+ msg = fedora_messaging.api.Message()
|
| |
+ msg.id = 123
|
| |
+ msg.topic = "org.fedoraproject.prod.mbs.module.state.change"
|
| |
+ msg.body = {
|
| |
+ "id": 123,
|
| |
+ "state_name": "ready",
|
| |
+ "name": "module",
|
| |
+ "stream": 6,
|
| |
+ "version": 6.1,
|
| |
+ }
|
| |
+
|
| |
+ config = {"koji_url": "koji_url", "mbs_url": "mbs_url"}
|
| |
+
|
| |
+ toddler.process(config, msg)
|
| |
+
|
| |
+ resp_mbs_module.raise_for_status.assert_called_once()
|
| |
+ req.get.assert_called_with("mbs_url/123?verbose=True", timeout=30)
|
| |
+
|
| |
+ assert client[pdc_api]._.mock_calls == [
|
| |
+ call(page_size=1),
|
| |
+ call(page_size=-1, variant_uid=uid),
|
| |
+ call(
|
| |
+ {
|
| |
+ "variant_id": "module",
|
| |
+ "variant_uid": uid,
|
| |
+ "variant_name": "module",
|
| |
+ "variant_version": 6,
|
| |
+ "variant_release": 6.1,
|
| |
+ "variant_type": "module",
|
| |
+ "koji_tag": "NA",
|
| |
+ "runtime_deps": [{"dependency": "dependency", "stream": "stream"}],
|
| |
+ "build_deps": [{"dependency": "dependency", "stream": "stream"}],
|
| |
+ "modulemd": "module",
|
| |
+ }
|
| |
+ ),
|
| |
+ ]
|
| |
+
|
| |
+ assert client[pdc_api][123].mock_calls == [
|
| |
+ call._.__iadd__(
|
| |
+ {
|
| |
+ "active": True,
|
| |
+ "rpms": [
|
| |
+ {
|
| |
+ "name": "rpm",
|
| |
+ "version": 1.0,
|
| |
+ "release": 1,
|
| |
+ "epoch": 0,
|
| |
+ "arch": "x86_64",
|
| |
+ "srpm_name": "rpm",
|
| |
+ "srpm_nevra": "rpm-1.0-1",
|
| |
+ }
|
| |
+ ],
|
| |
+ }
|
| |
+ )
|
| |
+ ]
|
| |
+
|
| |
+ assert mmd.upgrade.call_count == 2
|
| |
This toddler reacts on state change message coming from MBS and either
updates or create a new module in PDC.
This toddler is the equivalent to the pdc-updater handlers:
https://github.com/fedora-infra/pdc-updater/blob/develop/pdcupdater/handlers/modules.py
Signed-off-by: Michal Konečný mkonecny@redhat.com