Blame SOURCES/bz2050274-02-relax-OCF-1.0-parser.patch

f5f42f
From 65b30a04a234449cb4aa65606d47bf1d673592a4 Mon Sep 17 00:00:00 2001
f5f42f
From: Tomas Jelinek <tojeline@redhat.com>
f5f42f
Date: Wed, 9 Feb 2022 11:16:49 +0100
f5f42f
Subject: [PATCH 2/3] relax OCF 1.0 parser
f5f42f
f5f42f
---
f5f42f
 pcs/lib/resource_agent/facade.py              |  50 ++++--
f5f42f
 pcs/lib/resource_agent/ocf_transform.py       |  51 +++++-
f5f42f
 pcs/lib/resource_agent/xml.py                 |   8 +-
f5f42f
 .../tier0/lib/resource_agent/test_facade.py   |  44 +++++
f5f42f
 .../lib/resource_agent/test_ocf_transform.py  |  48 +++++-
f5f42f
 pcs_test/tier0/lib/resource_agent/test_xml.py | 155 ++++++++++--------
f5f42f
 6 files changed, 256 insertions(+), 100 deletions(-)
f5f42f
f5f42f
diff --git a/pcs/lib/resource_agent/facade.py b/pcs/lib/resource_agent/facade.py
f5f42f
index dea59a1a..8a65eb1c 100644
f5f42f
--- a/pcs/lib/resource_agent/facade.py
f5f42f
+++ b/pcs/lib/resource_agent/facade.py
f5f42f
@@ -2,12 +2,19 @@ from collections import defaultdict
f5f42f
 from dataclasses import replace as dc_replace
f5f42f
 from typing import Dict, Iterable, List, Optional, Set
f5f42f
 
f5f42f
+from lxml import etree
f5f42f
+
f5f42f
+from pcs import settings
f5f42f
 from pcs.common import reports
f5f42f
 from pcs.lib import validate
f5f42f
 from pcs.lib.external import CommandRunner
f5f42f
 
f5f42f
 from . import const
f5f42f
-from .error import ResourceAgentError, resource_agent_error_to_report_item
f5f42f
+from .error import (
f5f42f
+    ResourceAgentError,
f5f42f
+    resource_agent_error_to_report_item,
f5f42f
+    UnableToGetAgentMetadata,
f5f42f
+)
f5f42f
 from .name import name_to_void_metadata
f5f42f
 from .ocf_transform import ocf_version_to_ocf_unified
f5f42f
 from .pcs_transform import get_additional_trace_parameters, ocf_unified_to_pcs
f5f42f
@@ -195,24 +202,33 @@ class ResourceAgentFacadeFactory:
f5f42f
 
f5f42f
         name -- agent name to get a facade for
f5f42f
         """
f5f42f
-        metadata, raw_ocf_version = parse_metadata(
f5f42f
-            name,
f5f42f
-            load_metadata(self._runner, name),
f5f42f
-        )
f5f42f
-        if (
f5f42f
-            report_warnings
f5f42f
-            and raw_ocf_version not in const.SUPPORTED_OCF_VERSIONS
f5f42f
-        ):
f5f42f
-            self._report_processor.report(
f5f42f
-                reports.ReportItem.warning(
f5f42f
-                    reports.messages.AgentImplementsUnsupportedOcfVersionAssumedVersion(
f5f42f
-                        name.full_name,
f5f42f
-                        raw_ocf_version,
f5f42f
-                        sorted(const.SUPPORTED_OCF_VERSIONS),
f5f42f
-                        const.OCF_1_0,
f5f42f
+        dom_metadata = load_metadata(self._runner, name)
f5f42f
+        metadata, raw_ocf_version = parse_metadata(name, dom_metadata)
f5f42f
+        if report_warnings:
f5f42f
+            if raw_ocf_version not in const.SUPPORTED_OCF_VERSIONS:
f5f42f
+                self._report_processor.report(
f5f42f
+                    reports.ReportItem.warning(
f5f42f
+                        reports.messages.AgentImplementsUnsupportedOcfVersionAssumedVersion(
f5f42f
+                            name.full_name,
f5f42f
+                            raw_ocf_version,
f5f42f
+                            sorted(const.SUPPORTED_OCF_VERSIONS),
f5f42f
+                            const.OCF_1_0,
f5f42f
+                        )
f5f42f
                     )
f5f42f
                 )
f5f42f
-            )
f5f42f
+            if raw_ocf_version != const.OCF_1_1:
f5f42f
+                try:
f5f42f
+                    etree.RelaxNG(
f5f42f
+                        file=settings.path.ocf_1_0_schema
f5f42f
+                    ).assertValid(dom_metadata)
f5f42f
+                except etree.DocumentInvalid as e:
f5f42f
+                    self._report_processor.report(
f5f42f
+                        resource_agent_error_to_report_item(
f5f42f
+                            UnableToGetAgentMetadata(name.full_name, str(e)),
f5f42f
+                            severity=reports.ReportItemSeverity.warning(),
f5f42f
+                            is_stonith=name.is_stonith,
f5f42f
+                        )
f5f42f
+                    )
f5f42f
         return self._facade_from_metadata(ocf_version_to_ocf_unified(metadata))
f5f42f
 
f5f42f
     def void_facade_from_parsed_name(
f5f42f
diff --git a/pcs/lib/resource_agent/ocf_transform.py b/pcs/lib/resource_agent/ocf_transform.py
f5f42f
index e841b55e..7e6a14ad 100644
f5f42f
--- a/pcs/lib/resource_agent/ocf_transform.py
f5f42f
+++ b/pcs/lib/resource_agent/ocf_transform.py
f5f42f
@@ -67,20 +67,42 @@ def _ocf_1_1_to_ocf_unified(
f5f42f
         longdesc=metadata.longdesc,
f5f42f
         parameters=_ocf_1_1_parameter_list_to_ocf_unified(metadata.parameters),
f5f42f
         # OCF 1.1 actions are the same as in OCF 1.0
f5f42f
-        actions=_ocf_1_0_action_list_to_ocf_unified(metadata.actions),
f5f42f
+        actions=_ocf_1_1_action_list_to_ocf_unified(metadata.actions),
f5f42f
     )
f5f42f
 
f5f42f
 
f5f42f
 def _ocf_1_0_action_list_to_ocf_unified(
f5f42f
-    action_list: Iterable[
f5f42f
-        Union[ResourceAgentActionOcf1_0, ResourceAgentActionOcf1_1]
f5f42f
-    ],
f5f42f
+    action_list: Iterable[ResourceAgentActionOcf1_0],
f5f42f
 ) -> List[ResourceAgentAction]:
f5f42f
     """
f5f42f
     Transform OCF 1.0 actions to a universal format
f5f42f
 
f5f42f
     action_list -- actions according OCF 1.0
f5f42f
     """
f5f42f
+    return [
f5f42f
+        ResourceAgentAction(
f5f42f
+            name=action.name,
f5f42f
+            timeout=action.timeout,
f5f42f
+            interval=action.interval,
f5f42f
+            role=action.role,
f5f42f
+            start_delay=action.start_delay,
f5f42f
+            depth=action.depth,
f5f42f
+            automatic=_bool_value_legacy(action.automatic),
f5f42f
+            on_target=_bool_value_legacy(action.on_target),
f5f42f
+        )
f5f42f
+        for action in action_list
f5f42f
+        if action.name
f5f42f
+    ]
f5f42f
+
f5f42f
+
f5f42f
+def _ocf_1_1_action_list_to_ocf_unified(
f5f42f
+    action_list: Iterable[ResourceAgentActionOcf1_1],
f5f42f
+) -> List[ResourceAgentAction]:
f5f42f
+    """
f5f42f
+    Transform OCF 1.1 actions to a universal format
f5f42f
+
f5f42f
+    action_list -- actions according OCF 1.1
f5f42f
+    """
f5f42f
     return [
f5f42f
         ResourceAgentAction(
f5f42f
             name=action.name,
f5f42f
@@ -111,6 +133,8 @@ def _ocf_1_0_parameter_list_to_ocf_unified(
f5f42f
 
f5f42f
     result = []
f5f42f
     for parameter in parameter_list:
f5f42f
+        if not parameter.name:
f5f42f
+            continue
f5f42f
         result.append(
f5f42f
             ResourceAgentParameter(
f5f42f
                 name=parameter.name,
f5f42f
@@ -119,17 +143,17 @@ def _ocf_1_0_parameter_list_to_ocf_unified(
f5f42f
                 type=parameter.type,
f5f42f
                 default=parameter.default,
f5f42f
                 enum_values=parameter.enum_values,
f5f42f
-                required=_bool_value(parameter.required),
f5f42f
+                required=_bool_value_legacy(parameter.required),
f5f42f
                 advanced=False,
f5f42f
-                deprecated=_bool_value(parameter.deprecated),
f5f42f
+                deprecated=_bool_value_legacy(parameter.deprecated),
f5f42f
                 deprecated_by=sorted(deprecated_by_dict[parameter.name]),
f5f42f
                 deprecated_desc=None,
f5f42f
                 unique_group=(
f5f42f
                     f"{const.DEFAULT_UNIQUE_GROUP_PREFIX}{parameter.name}"
f5f42f
-                    if _bool_value(parameter.unique)
f5f42f
+                    if _bool_value_legacy(parameter.unique)
f5f42f
                     else None
f5f42f
                 ),
f5f42f
-                reloadable=_bool_value(parameter.unique),
f5f42f
+                reloadable=_bool_value_legacy(parameter.unique),
f5f42f
             )
f5f42f
         )
f5f42f
     return result
f5f42f
@@ -170,3 +194,14 @@ def _bool_value(value: Optional[str]) -> bool:
f5f42f
     value -- raw bool value
f5f42f
     """
f5f42f
     return value == "1"
f5f42f
+
f5f42f
+
f5f42f
+def _bool_value_legacy(value: Optional[str]) -> bool:
f5f42f
+    """
f5f42f
+    Transform raw bool value from metadata to bool type in backward compatible way
f5f42f
+
f5f42f
+    value -- raw bool value
f5f42f
+    """
f5f42f
+    return (
f5f42f
+        False if not value else value.lower() in {"true", "on", "yes", "y", "1"}
f5f42f
+    )
f5f42f
diff --git a/pcs/lib/resource_agent/xml.py b/pcs/lib/resource_agent/xml.py
f5f42f
index 1ba97216..0fc70527 100644
f5f42f
--- a/pcs/lib/resource_agent/xml.py
f5f42f
+++ b/pcs/lib/resource_agent/xml.py
f5f42f
@@ -94,9 +94,7 @@ def _metadata_xml_to_dom(metadata: str) -> _Element:
f5f42f
     """
f5f42f
     dom = xml_fromstring(metadata)
f5f42f
     ocf_version = _get_ocf_version(dom)
f5f42f
-    if ocf_version == const.OCF_1_0:
f5f42f
-        etree.RelaxNG(file=settings.path.ocf_1_0_schema).assertValid(dom)
f5f42f
-    elif ocf_version == const.OCF_1_1:
f5f42f
+    if ocf_version == const.OCF_1_1:
f5f42f
         etree.RelaxNG(file=settings.path.ocf_1_1_schema).assertValid(dom)
f5f42f
     return dom
f5f42f
 
f5f42f
@@ -230,7 +228,7 @@ def _parse_parameters_1_0(
f5f42f
         )
f5f42f
         result.append(
f5f42f
             ResourceAgentParameterOcf1_0(
f5f42f
-                name=str(parameter_el.attrib["name"]),
f5f42f
+                name=str(parameter_el.get("name", "")),
f5f42f
                 shortdesc=_get_shortdesc(parameter_el),
f5f42f
                 longdesc=_get_longdesc(parameter_el),
f5f42f
                 type=value_type,
f5f42f
@@ -286,7 +284,7 @@ def _parse_parameters_1_1(
f5f42f
 def _parse_actions_1_0(element: _Element) -> List[ResourceAgentActionOcf1_0]:
f5f42f
     return [
f5f42f
         ResourceAgentActionOcf1_0(
f5f42f
-            name=str(action.attrib["name"]),
f5f42f
+            name=str(action.get("name", "")),
f5f42f
             timeout=action.get("timeout"),
f5f42f
             interval=action.get("interval"),
f5f42f
             role=action.get("role"),
f5f42f
diff --git a/pcs_test/tier0/lib/resource_agent/test_facade.py b/pcs_test/tier0/lib/resource_agent/test_facade.py
f5f42f
index f6a9899c..313dfa2b 100644
f5f42f
--- a/pcs_test/tier0/lib/resource_agent/test_facade.py
f5f42f
+++ b/pcs_test/tier0/lib/resource_agent/test_facade.py
f5f42f
@@ -100,6 +100,13 @@ class ResourceAgentFacadeFactory(TestCase):
f5f42f
             </parameters>
f5f42f
         </resource-agent>
f5f42f
     """
f5f42f
+    _fixture_agent_not_valid_xml = """
f5f42f
+        <resource-agent name="agent">
f5f42f
+            <parameters>
f5f42f
+                <parameter label="something wrong"/>
f5f42f
+            </parameters>
f5f42f
+        </resource-agent>
f5f42f
+    """
f5f42f
     _fixture_fenced_xml = """
f5f42f
         <resource-agent name="pacemaker-fenced">
f5f42f
             <parameters>
f5f42f
@@ -172,6 +179,43 @@ class ResourceAgentFacadeFactory(TestCase):
f5f42f
         self.assertEqual(facade.metadata.name, name)
f5f42f
         self.assertTrue(facade.metadata.agent_exists)
f5f42f
 
f5f42f
+    def test_facade_ocf_1_0_not_valid(self):
f5f42f
+        name = ra.ResourceAgentName("service", None, "daemon")
f5f42f
+        self.config.runner.pcmk.load_agent(
f5f42f
+            agent_name="service:daemon",
f5f42f
+            stdout=self._fixture_agent_not_valid_xml,
f5f42f
+        )
f5f42f
+
f5f42f
+        env = self.env_assist.get_env()
f5f42f
+        facade = ra.ResourceAgentFacadeFactory(
f5f42f
+            env.cmd_runner(), env.report_processor
f5f42f
+        ).facade_from_parsed_name(name)
f5f42f
+        self.assertEqual(facade.metadata.name, name)
f5f42f
+        self.assertTrue(facade.metadata.agent_exists)
f5f42f
+        self.env_assist.assert_reports(
f5f42f
+            [
f5f42f
+                fixture.warn(
f5f42f
+                    reports.codes.UNABLE_TO_GET_AGENT_METADATA,
f5f42f
+                    agent=name.full_name,
f5f42f
+                    reason="Element parameter failed to validate attributes, line 3",
f5f42f
+                )
f5f42f
+            ]
f5f42f
+        )
f5f42f
+
f5f42f
+    def test_facade_ocf_1_0_not_valid_disabled_warning(self):
f5f42f
+        name = ra.ResourceAgentName("service", None, "daemon")
f5f42f
+        self.config.runner.pcmk.load_agent(
f5f42f
+            agent_name="service:daemon",
f5f42f
+            stdout=self._fixture_agent_not_valid_xml,
f5f42f
+        )
f5f42f
+
f5f42f
+        env = self.env_assist.get_env()
f5f42f
+        facade = ra.ResourceAgentFacadeFactory(
f5f42f
+            env.cmd_runner(), env.report_processor
f5f42f
+        ).facade_from_parsed_name(name, report_warnings=False)
f5f42f
+        self.assertEqual(facade.metadata.name, name)
f5f42f
+        self.assertTrue(facade.metadata.agent_exists)
f5f42f
+
f5f42f
     def test_facade_missing_agent(self):
f5f42f
         name = ra.ResourceAgentName("service", None, "daemon")
f5f42f
         self.config.runner.pcmk.load_agent(
f5f42f
diff --git a/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py b/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py
f5f42f
index 9e41b6af..d0de86e5 100644
f5f42f
--- a/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py
f5f42f
+++ b/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py
f5f42f
@@ -66,6 +66,18 @@ class OcfVersionToOcfUnified(TestCase):
f5f42f
                     obsoletes=None,
f5f42f
                     unique=None,
f5f42f
                 ),
f5f42f
+                ra.types.ResourceAgentParameterOcf1_0(
f5f42f
+                    name="",
f5f42f
+                    shortdesc="Parameters with no name are ignored",
f5f42f
+                    longdesc=None,
f5f42f
+                    type="string",
f5f42f
+                    default=None,
f5f42f
+                    enum_values=None,
f5f42f
+                    required=None,
f5f42f
+                    deprecated=None,
f5f42f
+                    obsoletes=None,
f5f42f
+                    unique=None,
f5f42f
+                ),
f5f42f
                 ra.types.ResourceAgentParameterOcf1_0(
f5f42f
                     name="param_2",
f5f42f
                     shortdesc="param_2 shortdesc",
f5f42f
@@ -109,10 +121,10 @@ class OcfVersionToOcfUnified(TestCase):
f5f42f
                     type="string",
f5f42f
                     default=None,
f5f42f
                     enum_values=None,
f5f42f
-                    required="1",
f5f42f
-                    deprecated="1",
f5f42f
+                    required="yeS",
f5f42f
+                    deprecated="True",
f5f42f
                     obsoletes="param_4",
f5f42f
-                    unique="1",
f5f42f
+                    unique="on",
f5f42f
                 ),
f5f42f
                 ra.types.ResourceAgentParameterOcf1_0(
f5f42f
                     name="param_6",
f5f42f
@@ -138,6 +150,16 @@ class OcfVersionToOcfUnified(TestCase):
f5f42f
                     automatic=None,
f5f42f
                     on_target=None,
f5f42f
                 ),
f5f42f
+                ra.types.ResourceAgentActionOcf1_0(
f5f42f
+                    name="",
f5f42f
+                    timeout=None,
f5f42f
+                    interval=None,
f5f42f
+                    role=None,
f5f42f
+                    start_delay=None,
f5f42f
+                    depth=None,
f5f42f
+                    automatic=None,
f5f42f
+                    on_target=None,
f5f42f
+                ),
f5f42f
                 ra.types.ResourceAgentActionOcf1_0(
f5f42f
                     name="action_2",
f5f42f
                     timeout="12",
f5f42f
@@ -158,6 +180,16 @@ class OcfVersionToOcfUnified(TestCase):
f5f42f
                     automatic="1",
f5f42f
                     on_target="0",
f5f42f
                 ),
f5f42f
+                ra.types.ResourceAgentActionOcf1_0(
f5f42f
+                    name="action_4",
f5f42f
+                    timeout=None,
f5f42f
+                    interval=None,
f5f42f
+                    role=None,
f5f42f
+                    start_delay=None,
f5f42f
+                    depth=None,
f5f42f
+                    automatic="yes",
f5f42f
+                    on_target="True",
f5f42f
+                ),
f5f42f
             ],
f5f42f
         )
f5f42f
         metadata_out = ra.ResourceAgentMetadata(
f5f42f
@@ -289,6 +321,16 @@ class OcfVersionToOcfUnified(TestCase):
f5f42f
                     automatic=True,
f5f42f
                     on_target=False,
f5f42f
                 ),
f5f42f
+                ra.ResourceAgentAction(
f5f42f
+                    name="action_4",
f5f42f
+                    timeout=None,
f5f42f
+                    interval=None,
f5f42f
+                    role=None,
f5f42f
+                    start_delay=None,
f5f42f
+                    depth=None,
f5f42f
+                    automatic=True,
f5f42f
+                    on_target=True,
f5f42f
+                ),
f5f42f
             ],
f5f42f
         )
f5f42f
         self.assertEqual(
f5f42f
diff --git a/pcs_test/tier0/lib/resource_agent/test_xml.py b/pcs_test/tier0/lib/resource_agent/test_xml.py
f5f42f
index 26bbbb7d..ea055ee2 100644
f5f42f
--- a/pcs_test/tier0/lib/resource_agent/test_xml.py
f5f42f
+++ b/pcs_test/tier0/lib/resource_agent/test_xml.py
f5f42f
@@ -164,8 +164,13 @@ class MetadataXmlToDom(TestCase):
f5f42f
             ra.xml._metadata_xml_to_dom("not an xml")
f5f42f
 
f5f42f
     def test_no_version_not_valid(self):
f5f42f
-        with self.assertRaises(etree.DocumentInvalid):
f5f42f
-            ra.xml._metadata_xml_to_dom("<resource-agent/>")
f5f42f
+        # pylint: disable=no-self-use
f5f42f
+        metadata = """
f5f42f
+            <resource-agent/>
f5f42f
+        """
f5f42f
+        assert_xml_equal(
f5f42f
+            metadata, etree_to_str(ra.xml._metadata_xml_to_dom(metadata))
f5f42f
+        )
f5f42f
 
f5f42f
     def test_no_version_valid(self):
f5f42f
         # pylint: disable=no-self-use
f5f42f
@@ -178,14 +183,15 @@ class MetadataXmlToDom(TestCase):
f5f42f
         )
f5f42f
 
f5f42f
     def test_ocf_1_0_not_valid(self):
f5f42f
-        with self.assertRaises(etree.DocumentInvalid):
f5f42f
-            ra.xml._metadata_xml_to_dom(
f5f42f
-                """
f5f42f
-                    <resource-agent>
f5f42f
-                        <version>1.0</version>
f5f42f
-                    </resource-agent>
f5f42f
-                """
f5f42f
-            )
f5f42f
+        # pylint: disable=no-self-use
f5f42f
+        metadata = """
f5f42f
+            <resource-agent>
f5f42f
+                <version>1.0</version>
f5f42f
+            </resource-agent>
f5f42f
+        """
f5f42f
+        assert_xml_equal(
f5f42f
+            metadata, etree_to_str(ra.xml._metadata_xml_to_dom(metadata))
f5f42f
+        )
f5f42f
 
f5f42f
     def test_ocf_1_0_valid(self):
f5f42f
         # pylint: disable=no-self-use
f5f42f
@@ -273,19 +279,16 @@ class LoadMetadata(TestCase):
f5f42f
 
f5f42f
     def test_not_valid_xml(self):
f5f42f
         agent_name = ra.ResourceAgentName("ocf", "pacemaker", "Dummy")
f5f42f
+        metadata = "<resource-agent/>"
f5f42f
         self.config.runner.pcmk.load_agent(
f5f42f
             agent_name="ocf:pacemaker:Dummy",
f5f42f
-            stdout="<resource-agent/>",
f5f42f
+            stdout=metadata,
f5f42f
         )
f5f42f
 
f5f42f
         env = self.env_assist.get_env()
f5f42f
-        with self.assertRaises(ra.UnableToGetAgentMetadata) as cm:
f5f42f
-            ra.xml.load_metadata(env.cmd_runner(), agent_name)
f5f42f
-        self.assertEqual(cm.exception.agent_name, "ocf:pacemaker:Dummy")
f5f42f
-        self.assertTrue(
f5f42f
-            cm.exception.message.startswith(
f5f42f
-                "Element resource-agent failed to validate"
f5f42f
-            )
f5f42f
+        assert_xml_equal(
f5f42f
+            metadata,
f5f42f
+            etree_to_str(ra.xml.load_metadata(env.cmd_runner(), agent_name)),
f5f42f
         )
f5f42f
 
f5f42f
 
f5f42f
@@ -335,16 +338,15 @@ class LoadFakeAgentMetadata(TestCase):
f5f42f
 
f5f42f
     def test_not_valid_xml(self):
f5f42f
         agent_name = ra.const.PACEMAKER_FENCED
f5f42f
-        self.config.runner.pcmk.load_fenced_metadata(stdout="<resource-agent/>")
f5f42f
+        metadata = "<resource-agent/>"
f5f42f
+        self.config.runner.pcmk.load_fenced_metadata(stdout=metadata)
f5f42f
 
f5f42f
         env = self.env_assist.get_env()
f5f42f
-        with self.assertRaises(ra.UnableToGetAgentMetadata) as cm:
f5f42f
-            ra.xml.load_fake_agent_metadata(env.cmd_runner(), agent_name)
f5f42f
-        self.assertEqual(cm.exception.agent_name, "pacemaker-fenced")
f5f42f
-        self.assertTrue(
f5f42f
-            cm.exception.message.startswith(
f5f42f
-                "Element resource-agent failed to validate"
f5f42f
-            )
f5f42f
+        assert_xml_equal(
f5f42f
+            metadata,
f5f42f
+            etree_to_str(
f5f42f
+                ra.xml.load_fake_agent_metadata(env.cmd_runner(), agent_name)
f5f42f
+            ),
f5f42f
         )
f5f42f
 
f5f42f
 
f5f42f
@@ -549,19 +551,37 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
f5f42f
         )
f5f42f
 
f5f42f
     def test_parameters_empty_parameter(self):
f5f42f
-        # parameters must have at least 'name' attribute
f5f42f
-        with self.assertRaises(ra.UnableToGetAgentMetadata):
f5f42f
-            self.parse(
f5f42f
-                self.xml(
f5f42f
-                    """
f5f42f
-                        <resource-agent>
f5f42f
-                            <parameters>
f5f42f
-                                <parameter/>
f5f42f
-                            </parameters>
f5f42f
-                        </resource-agent>
f5f42f
-                    """
f5f42f
-                )
f5f42f
-            )
f5f42f
+        self.assert_parse_result(
f5f42f
+            self.xml(
f5f42f
+                """
f5f42f
+                    <resource-agent>
f5f42f
+                        <parameters>
f5f42f
+                            <parameter/>
f5f42f
+                        </parameters>
f5f42f
+                    </resource-agent>
f5f42f
+                """
f5f42f
+            ),
f5f42f
+            ResourceAgentMetadataOcf1_0(
f5f42f
+                self.agent_name,
f5f42f
+                shortdesc=None,
f5f42f
+                longdesc=None,
f5f42f
+                parameters=[
f5f42f
+                    ResourceAgentParameterOcf1_0(
f5f42f
+                        name="",
f5f42f
+                        shortdesc=None,
f5f42f
+                        longdesc=None,
f5f42f
+                        type="string",
f5f42f
+                        default=None,
f5f42f
+                        enum_values=None,
f5f42f
+                        required=None,
f5f42f
+                        deprecated=None,
f5f42f
+                        obsoletes=None,
f5f42f
+                        unique=None,
f5f42f
+                    )
f5f42f
+                ],
f5f42f
+                actions=[],
f5f42f
+            ),
f5f42f
+        )
f5f42f
 
f5f42f
     def test_parameters_minimal(self):
f5f42f
         self.assert_parse_result(
f5f42f
@@ -708,19 +728,35 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
f5f42f
         )
f5f42f
 
f5f42f
     def test_actions_empty_action(self):
f5f42f
-        # actions must have at least 'name' attribute
f5f42f
-        with self.assertRaises(ra.UnableToGetAgentMetadata):
f5f42f
-            self.parse(
f5f42f
-                self.xml(
f5f42f
-                    """
f5f42f
-                        <resource-agent>
f5f42f
-                            <actions>
f5f42f
-                                <action/>
f5f42f
-                            </actions>
f5f42f
-                        </resource-agent>
f5f42f
-                    """
f5f42f
-                )
f5f42f
-            )
f5f42f
+        self.assert_parse_result(
f5f42f
+            self.xml(
f5f42f
+                """
f5f42f
+                    <resource-agent>
f5f42f
+                        <actions>
f5f42f
+                            <action/>
f5f42f
+                        </actions>
f5f42f
+                    </resource-agent>
f5f42f
+                """
f5f42f
+            ),
f5f42f
+            ResourceAgentMetadataOcf1_0(
f5f42f
+                self.agent_name,
f5f42f
+                shortdesc=None,
f5f42f
+                longdesc=None,
f5f42f
+                parameters=[],
f5f42f
+                actions=[
f5f42f
+                    ResourceAgentActionOcf1_0(
f5f42f
+                        name="",
f5f42f
+                        timeout=None,
f5f42f
+                        interval=None,
f5f42f
+                        role=None,
f5f42f
+                        start_delay=None,
f5f42f
+                        depth=None,
f5f42f
+                        automatic=None,
f5f42f
+                        on_target=None,
f5f42f
+                    ),
f5f42f
+                ],
f5f42f
+            ),
f5f42f
+        )
f5f42f
 
f5f42f
     def test_actions_multiple(self):
f5f42f
         self.assert_parse_result(
f5f42f
@@ -787,21 +823,6 @@ class ParseOcf10NoVersion(ParseOcf10BaseMixin, TestCase):
f5f42f
 class ParseOcf10UnsupportedVersion(ParseOcf10BaseMixin, TestCase):
f5f42f
     ocf_version = "0.1.2"
f5f42f
 
f5f42f
-    # These tests test that pcs raises an error if an agent doesn't conform to
f5f42f
-    # OCF schema. There is, however, no validation against OCF schema for
f5f42f
-    # agents with unsupported OCF version. That means no error message, pcs
f5f42f
-    # tries to process the agent and crashes. However bad that sounds, it's
f5f42f
-    # indended as that's how pcs behaved before OCF 1.1 was implemented.
f5f42f
-    # There's therefore no point in running these tests.
f5f42f
-
f5f42f
-    def test_parameters_empty_parameter(self):
f5f42f
-        # parameters must have at least 'name' attribute
f5f42f
-        pass
f5f42f
-
f5f42f
-    def test_actions_empty_action(self):
f5f42f
-        # actions must have at least 'name' attribute
f5f42f
-        pass
f5f42f
-
f5f42f
 
f5f42f
 class ParseOcf10ExplicitVersion(ParseOcf10BaseMixin, TestCase):
f5f42f
     ocf_version = "1.0"
f5f42f
-- 
f5f42f
2.34.1
f5f42f