Repository: RedHatInsights/insights-core

Issue:
Unsuitable parse error in `Lssap`
Too many `parser_error` reported by the Rule Analysis Tool, e.g:

~~~
Lssap: Invalid instance parsed in content: ['DVEBMGS', 'SMDA']
Lssap: Invalid instance parsed in content: ['J', 'SMDA']
Lssap: Invalid instance parsed in content: ['J', 'SCS', 'SMDA']
~~~

In which, the `DVEBMGS`, `SMDA`, `J`, `SCS` or others are also good SAP instances


Discussion:

Resolving patch:
diff --git a/insights/parsers/lssap.py b/insights/parsers/lssap.py
--- a/insights/parsers/lssap.py
+++ b/insights/parsers/lssap.py
@@ -19,18 +19,12 @@
    HA2|  51|       D51|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D51/exe
 
 Examples:
-    >>> lssap = shared[Lssap]
-    >>> lssap.instances()
+    >>> lssap.instances
     ['D16', 'D22', 'D50', 'D51']
     >>> lssap.version('D51')
-    '749, path 10, changelist 1698137'
-    >>> lssap.is_instance()
-    True
+    '749, patch 10, changelist 1698137'
     >>> lssap.is_hana()
     False
-    >>> lssap.data[3]
-    {'SID': 'HA2', 'Nr': '51', 'Instance': 'D51', 'SAPLOCALHOST': 'lu0417',
-     'Version': '749, path 10, changelist 1698137', 'DIR_EXECUTABLE': '/usr/sap/HA2/D51/exe'}
     >>> lssap.data[3]['Instance']
     'D51'
 """
@@ -43,22 +37,18 @@
 class Lssap(CommandParser):
     """Class to parse ``lssap`` command output.
 
+    Raises:
+        ParseException: Raised if any error occurs parsing the content.
+
     Attributes:
         data (list): List of dicts, where the keys in each dict are the column
             headers and each item in the list represents a SID.
-
-    Raises:
-        ParseException: Raised if any error occurs parsing the content.
+        sid (list): List of the SIDs from the SID column.
+        instances (list): List of instances running on the system.
+        instance_types (list): List of instance types running on the system.
     """
-    instance_dict = {'D': 'netweaver',
-                     'HDB': 'hana',
-                     'ASCS': 'ascs'}
-
-    def __init__(self, *args, **kwargs):
-        self.data = []
-        super(Lssap, self).__init__(*args, **kwargs)
-
     def parse_content(self, content):
+        self.data = []
         # remove lssap version and bar text from content
         clean_content = content[2:-1]
         if len(clean_content) > 0 and "SID" in clean_content[0]:
@@ -66,12 +56,9 @@ def parse_content(self, content):
         else:
             raise ParseException("Lssap: Unable to parse {0} line(s) of content: ({1})".format(len(content), content))
 
-        self.running_inst_types = [row["Instance"].rstrip('1234567890') for row in self.data if "Instance" in row]
-
-        invalid_inst = [i for i in self.running_inst_types if i not in self.instance_dict]
-
-        if invalid_inst:
-            raise ParseException("Lssap: Invalid instance parsed in content: {0}".format(invalid_inst))
+        self.sid = sorted(set(row["SID"] for row in self.data if "SID" in row))
+        self.instances = [row["Instance"] for row in self.data if "Instance" in row]
+        self.instance_types = sorted(set(inst.rstrip('1234567890') for inst in self.instances))
 
     def version(self, instance):
         """str: returns the Version column corresponding to the ``instance`` in
@@ -81,24 +68,14 @@ def version(self, instance):
             if instance == row['Instance']:
                 return row["Version"]
 
-    @property
-    def instances(self):
-        """list: List instances running on the system."""
-        return [row["Instance"] for row in self.data if "Instance" in row]
-
-    @property
-    def sid(self):
-        """list: Returns a list of the SIDs from the SID column."""
-        return list(set(row["SID"] for row in self.data if "SID" in row))
-
     def is_netweaver(self):
         """bool: SAP Netweaver is running on the system."""
-        return 'D' in list(set(self.running_inst_types) & set(self.instance_dict.keys()))
+        return 'D' in self.instance_types
 
     def is_hana(self):
-        """bool: SAP Hana is running on the system."""
-        return 'HDB' in list(set(self.running_inst_types) & set(self.instance_dict.keys()))
+        """bool: SAP HANA is running on the system."""
+        return 'HDB' in self.instance_types
 
     def is_ascs(self):
         """bool: SAP System Central Services is running on the system."""
-        return 'ASCS' in list(set(self.running_inst_types) & set(self.instance_dict.keys()))
+        return 'ASCS' in self.instance_types


Test patch:
diff --git a/insights/parsers/tests/test_lssap.py b/insights/parsers/tests/test_lssap.py
--- a/insights/parsers/tests/test_lssap.py
+++ b/insights/parsers/tests/test_lssap.py
@@ -1,6 +1,7 @@
 from ...parsers import lssap, ParseException
 from ...tests import context_wrap
 from ...util import keys_in
+import doctest
 import pytest
 
 Lssap_BAD = """
@@ -25,7 +26,6 @@
   HA2|  22|       D22|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D22/exe
   HA2|  50|       D50|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D50/exe
   HA2|  51|       D51|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D51/exe
-  HA2|  52|       D52|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D52/exe
 ==========================================
 """.strip()
 
@@ -45,24 +45,19 @@
 ==========================================
 """.strip()
 
-Lssap_bad_instance_TEST = """
- - lssap version 1.0 -
-==========================================
-  SID   Nr   Instance    SAPLOCALHOST                        Version                 DIR_EXECUTABLE
-  HA2|  16|       B16|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D16/exe
-  HA2|  22|       QR22|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D22/exe
-  HA2|  50|       DS0|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D50/exe
-==========================================
-""".strip()
-
 Lssap_runAll_Test = """
  - lssap version 1.0 -
 ==========================================
   SID   Nr   Instance    SAPLOCALHOST                        Version                 DIR_EXECUTABLE
   HA2|  16|       D16|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D16/exe
   HA2|  22|       D22|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/D22/exe
-  HA2|  16|       HDB16|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/HDB16/exe
-  HA2|  16|       ASCS16|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/ASCS16/exe
+  HA2|  16|     HDB16|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/HDB16/exe
+  HA2|  16|    ASCS16|         lu0417|749, patch 10, changelist 1698137|          /usr/sap/HA2/ASCS16/exe
+  DA1|  97|    SMDA97|         l0116a|745, patch 100, changelist 1652052|         /usr/sap/DA1/SMDA97/exe
+  DAA|  98|    SMDA98|         l0116a|745, patch 100, changelist 1652052|         /usr/sap/DAA/SMDA98/exe
+  MHP|  00|     HDB00|         l0116a|749, patch 315, changelist 1787247|         /usr/sap/MHP/HDB00/exe
+  MEP|  02|    ASCS02|         l0116a|745, patch 600, changelist 1791210|         /usr/sap/MEP/ASCS02/exe
+  MEP|  01| DVEBMGS01|         l0116a|745, patch 600, changelist 1791210|         /usr/sap/MEP/DVEBMGS01/exe
 ==========================================
 """.strip()
 
@@ -80,11 +75,10 @@
 """.strip()
 
 
-def test_lists():
-    sap = lssap.Lssap(context_wrap(Lssap_runAll_Test))
-    assert sap.instances == ["D16", "D22", "HDB16", "ASCS16"]
-    assert sap.sid == ["HA2"]
-    assert sap.version("D16") == "749, patch 10, changelist 1698137"
+def test_doc_examples():
+    env = {'lssap': lssap.Lssap(context_wrap(Lssap_nw_TEST))}
+    failed, total = doctest.testmod(lssap, globs=env)
+    assert failed == 0
 
 
 def test_lssap_netweaver():
@@ -122,13 +116,18 @@ def test_lssap_ascs():
 
 def test_all():
     sap = lssap.Lssap(context_wrap(Lssap_runAll_Test))
-    data = sap.data
-    assert data[1] == {"SID": "HA2", "Nr": "22", "Instance": "D22", "SAPLOCALHOST": "lu0417",
-                       "Version": "749, patch 10, changelist 1698137",
-                       "DIR_EXECUTABLE": "/usr/sap/HA2/D22/exe"}
+    assert sap.sid == ['DA1', 'DAA', 'HA2', 'MEP', 'MHP']
+    assert sap.instances == ['D16', 'D22', 'HDB16', 'ASCS16', 'SMDA97', 'SMDA98', 'HDB00', 'ASCS02', 'DVEBMGS01']
+    assert sap.data[1] == {"SID": "HA2", "Nr": "22", "Instance": "D22", "SAPLOCALHOST": "lu0417",
+                           "Version": "749, patch 10, changelist 1698137",
+                           "DIR_EXECUTABLE": "/usr/sap/HA2/D22/exe"}
     assert sap.is_netweaver() is True
     assert sap.is_hana() is True
     assert sap.is_ascs() is True
+    assert 'SMDA' in sap.instance_types
+    assert 'DVEBMGS01' in sap.instances
+    assert sap.version("D16") == "749, patch 10, changelist 1698137"
+    assert sap.version("D06") is None
 
 
 def test_fail():
@@ -147,7 +146,3 @@ def test_fail():
     with pytest.raises(ParseException) as excinfo:
         lssap.Lssap(context_wrap(Lssap_BAD_3))
     assert "Lssap: Unable to parse 2 line(s) of content: (['HA2 | N16 | D16', 'HB2 | foo | bar'])" in str(excinfo)
-
-    with pytest.raises(ParseException) as excinfo:
-        lssap.Lssap(context_wrap(Lssap_bad_instance_TEST))
-    assert "Lssap: Invalid instance parsed in content: ['B', 'QR', 'DS']" in str(excinfo)