File backport_complex_xmlrpc_objects_and_logger_spam.patch of Package cobbler

Index: cobbler/items/item.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/items/item.py b/cobbler/items/item.py
--- a/cobbler/items/item.py	(revision 5c498dbf2af6e3782b37605a477759e1aacc16b2)
+++ b/cobbler/items/item.py	(revision 7371e1eeb7b735edd22897c5aba35987f295391f)
@@ -974,7 +974,7 @@
             parent = parent.parent
             # FIXME: Now get the object and check its existence
         results.append(self.api.settings())
-        self.logger.info(
+        self.logger.debug(
             "grab_tree found %s children (including settings) of this object",
             len(results),
         )
Index: config/cobbler/logging_config.conf
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/cobbler/logging_config.conf b/config/cobbler/logging_config.conf
--- a/config/cobbler/logging_config.conf	(revision 5c498dbf2af6e3782b37605a477759e1aacc16b2)
+++ b/config/cobbler/logging_config.conf	(revision 7371e1eeb7b735edd22897c5aba35987f295391f)
@@ -19,7 +19,7 @@
 
 [handler_stdout]
 class=StreamHandler
-level=WARNING
+level=INFO
 formatter=stdout
 args=(sys.stdout,)
 
@@ -34,7 +34,7 @@
 
 [handler_FileLogger]
 class=FileHandler
-level=DEBUG
+level=INFO
 formatter=Logfile
 args=('/var/log/cobbler/cobbler.log', 'a')
 
Index: cobbler/items/distro.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/items/distro.py b/cobbler/items/distro.py
--- a/cobbler/items/distro.py	(revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/cobbler/items/distro.py	(revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -34,6 +34,8 @@
     A Cobbler distribution object
     """
 
+    # Constants
+    TYPE_NAME = "distro"
     COLLECTION_TYPE = "distro"
 
     def __init__(self, api, *args, **kwargs):
Index: cobbler/items/system.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/items/system.py b/cobbler/items/system.py
--- a/cobbler/items/system.py	(revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/cobbler/items/system.py	(revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -730,6 +730,8 @@
     A Cobbler system object.
     """
 
+    # Constants
+    TYPE_NAME = "system"
     COLLECTION_TYPE = "system"
 
     def __init__(self, api, *args, **kwargs):
Index: cobbler/remote.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/remote.py b/cobbler/remote.py
--- a/cobbler/remote.py	(revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/cobbler/remote.py	(revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -34,6 +34,7 @@
 from typing import Dict, List, Optional, Union
 from xmlrpc.server import SimpleXMLRPCRequestHandler
 
+from cobbler import enums
 from cobbler import autoinstall_manager
 from cobbler import configgen
 from cobbler.items import item, package, system, image, profile, repo, mgmtclass, distro, file, menu
@@ -712,7 +713,38 @@
         .. seealso:: Logically identical to :func:`~cobbler.api.CobblerAPI.get_item_resolved_value`
         """
         self._log("get_item_resolved_value(%s)" % item_uuid, attribute=attribute)
-        return self.api.get_item_resolved_value(item_uuid, attribute)
+        return_value = self.api.get_item_resolved_value(item_uuid, attribute)
+        if return_value is None:
+            self._log(
+                "get_item_resolved_value(%s): returned None" % item_uuid,
+                attribute=attribute,
+            )
+            raise ValueError(
+                'None is not a valid value for the resolved attribute "%s". Please fix the item(s) '
+                'starting at uuid "%s"' % (attribute, item_uuid)
+            )
+        elif isinstance(return_value, enums.ConvertableEnum):
+            return return_value.value
+        elif isinstance(
+            return_value,
+            (utils.DHCP, enums.NetworkInterfaceType, enums.BaudRates, item.Item),
+        ):
+            return return_value.name
+        elif isinstance(return_value, dict):
+            return self.xmlrpc_hacks(return_value)
+
+        if not isinstance(
+            return_value, (str, int, float, bool, tuple, bytes, bytearray, dict, list)
+        ):
+            self._log(
+                "get_item_resolved_value(%s): Cannot return XML-RPC compliant type. Please add a case to convert"
+                ' type "%s" to an XML-RPC compliant type!'
+                % (item_uuid, type(return_value))
+            )
+            raise ValueError(
+                "Cannot return XML-RPC compliant type. See logs for more information!"
+            )
+        return return_value
 
     def get_item(self, what: str, name: str, flatten=False, resolved: bool = False):
         """
Index: tests/xmlrpcapi/non_object_calls_test.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/tests/xmlrpcapi/non_object_calls_test.py b/tests/xmlrpcapi/non_object_calls_test.py
--- a/tests/xmlrpcapi/non_object_calls_test.py	(revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/tests/xmlrpcapi/non_object_calls_test.py	(revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -4,6 +4,8 @@
 import time
 import re
 
+from tests.conftest import does_not_raise
+
 TEST_POWER_MANAGEMENT = True
 TEST_SYSTEM = ""
 
@@ -186,8 +188,26 @@
     assert match_obj
 
 
+@pytest.mark.parametrize(
+    "input_attribute,checked_object,expected_result,expected_exception",
+    [
+        ("kernel_options", "system", {"a": "1", "b": "2", "d": "~"}, does_not_raise()),
+        ("arch", "distro", "x86_64", does_not_raise()),
+        ("distro", "profile", "testdistro_item_resolved_value", does_not_raise()),
+        ("profile", "system", "testprofile_item_resolved_value", does_not_raise()),
+    ],
+)
 def test_get_item_resolved_value(
-    remote, token, create_distro, create_profile, create_system, create_kernel_initrd
+    remote,
+    token,
+    create_distro,
+    create_profile,
+    create_system,
+    create_kernel_initrd,
+    input_attribute,
+    checked_object,
+    expected_result,
+    expected_exception,
 ):
     # Arrange
     fk_kernel = "vmlinuz1"
@@ -203,11 +223,18 @@
     create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
     test_system_handle = create_system(name_system, name_profile)
     remote.modify_system(test_system_handle, "kernel_options", "!c !e", token=token)
-    test_system = remote.get_system(name_system, token=token)
-    expected_result = {"a": "1", "b": "2", "d": None}
+    if checked_object == "distro":
+        test_item = remote.get_distro(name_distro, token=token)
+    elif checked_object == "profile":
+        test_item = remote.get_profile(name_profile, token=token)
+    elif checked_object == "system":
+        test_item = remote.get_system(name_system, token=token)
+    else:
+        raise ValueError("checked_object has wrong value")
 
     # Act
-    result = remote.get_item_resolved_value(test_system.get("uid"), "kernel_options")
+    with expected_exception:
+        result = remote.get_item_resolved_value(test_item.get("uid"), input_attribute)
 
-    # Assert
-    assert expected_result == result
+        # Assert
+        assert expected_result == result
Index: cobbler/remote.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/remote.py b/cobbler/remote.py
--- a/cobbler/remote.py	(revision cb840ce25e78aa26349e3b23065b0fdf78fbadbc)
+++ b/cobbler/remote.py	(revision 8398a921c898744929afa1620efa70859d5463bb)
@@ -731,6 +731,20 @@
         ):
             return return_value.name
         elif isinstance(return_value, dict):
+            if (
+                attribute == "interfaces"
+                and len(return_value) > 0
+                and all(
+                    isinstance(value, system.NetworkInterface)
+                    for value in return_value.values()
+                )
+            ):
+                interface_return_value = {}
+                for interface_name in return_value:
+                    interface_return_value[interface_name] = return_value[
+                        interface_name
+                    ].to_dict(resolved=True)
+                return interface_return_value
             return self.xmlrpc_hacks(return_value)
 
         if not isinstance(
Index: tests/xmlrpcapi/non_object_calls_test.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/tests/xmlrpcapi/non_object_calls_test.py b/tests/xmlrpcapi/non_object_calls_test.py
--- a/tests/xmlrpcapi/non_object_calls_test.py	(revision cb840ce25e78aa26349e3b23065b0fdf78fbadbc)
+++ b/tests/xmlrpcapi/non_object_calls_test.py	(revision 8398a921c898744929afa1620efa70859d5463bb)
@@ -195,6 +195,40 @@
         ("arch", "distro", "x86_64", does_not_raise()),
         ("distro", "profile", "testdistro_item_resolved_value", does_not_raise()),
         ("profile", "system", "testprofile_item_resolved_value", does_not_raise()),
+        (
+            "interfaces",
+            "system",
+            {
+                "eth0": {
+                    "bonding_opts": "",
+                    "bridge_opts": "",
+                    "cnames": [],
+                    "connected_mode": False,
+                    "dhcp_tag": "",
+                    "dns_name": "",
+                    "if_gateway": "",
+                    "interface_master": "",
+                    "interface_type": "NA",
+                    "ip_address": "",
+                    "ipv6_address": "",
+                    "ipv6_default_gateway": "",
+                    "ipv6_mtu": "",
+                    "ipv6_prefix": "",
+                    "ipv6_secondaries": [],
+                    "ipv6_static_routes": [],
+                    "mac_address": "aa:bb:cc:dd:ee:ff",
+                    "management": False,
+                    "mtu": "",
+                    "netmask": "",
+                    "static": False,
+                    "static_routes": [],
+                    "virt_bridge": "",
+                }
+            },
+            does_not_raise(),
+        ),
+        ("modify_interface", "system", {}, pytest.raises(ValueError)),
+        ("doesnt_exist", "system", {}, pytest.raises(AttributeError)),
     ],
 )
 def test_get_item_resolved_value(
@@ -223,6 +257,12 @@
     create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
     test_system_handle = create_system(name_system, name_profile)
     remote.modify_system(test_system_handle, "kernel_options", "!c !e", token=token)
+    remote.modify_system(
+        test_system_handle,
+        "modify_interface",
+        {"macaddress-eth0": "aa:bb:cc:dd:ee:ff"},
+        token=token,
+    )
     if checked_object == "distro":
         test_item = remote.get_distro(name_distro, token=token)
     elif checked_object == "profile":

openSUSE Build Service is sponsored by