prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  ifcfg parser to support for MASTER and TEAM_MASTER keys slave type
  We need to update the ifcfg parser to support TEAMING and BONDING slave type in the configuration file, so, that we can use MASTER' and 'TEAM_MASTER' keys in raw format.
  
  For ex-  `obj['MASTER']="'bond0'"` or `obj['TEAM_MASTER']="'team0'"`
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `insights/parsers/ifcfg.py`
  Content:
  ```
  1 """
  2 IfCFG - files ``/etc/sysconfig/network-scripts/ifcfg-*``
  3 ========================================================
  4 
  5 IfCFG is a parser for the network interface definition files in
  6 ``/etc/sysconfig/network-scripts``.  These are pulled into the network
  7 scripts using ``source``, so they are mainly ``bash`` environment
  8 declarations of the form **KEY=value**.  These are stored in the ``data``
  9 property as a dictionary.  Quotes surrounding the value
  10 
  11 Three options are handled differently:
  12 
  13 * ``BONDING_OPTS`` is usually a quoted list of key=value arguments separated
  14   by spaces.
  15 * ``TEAM_CONFIG`` and ``TEAM_PORT_CONFIG`` are treated as JSON stored as a
  16   single string.  Double quotes within the string are escaped using double
  17   back slashes, and these are removed so that the quoting is preserved.
  18 
  19 Because this parser reads multiple files, the interfaces are stored as a
  20 list within the parser and need to be iterated through in order to find
  21 specific interfaces.
  22 
  23 Sample configuration from a teamed interface in file ``/etc/sysconfig/network-scripts/ifcfg-team1``::
  24 
  25     DEVICE=team1
  26     DEVICETYPE=Team
  27     ONBOOT=yes
  28     NETMASK=255.255.252.0
  29     IPADDR=192.168.0.1
  30     TEAM_CONFIG='{"runner": {"name": "lacp", "active": "true", "tx_hash": ["eth", "ipv4"]}, "tx_balancer": {"name": "basic"}, "link_watch": {"name": "ethtool"}}'
  31 
  32 Examples:
  33 
  34     >>> for nic in shared[IfCFG]: # Parser contains list of all interfaces
  35     ...     print 'NIC:', nic.iname
  36     ...     print 'IP address:', nic['IPADDR']
  37     ...     if 'TEAM_CONFIG' in nic:
  38     ...         print 'Team runner name:', nic['TEAM_CONFIG']['runner']['name']
  39     ...
  40     NIC: team1
  41     IP addresss: 192.168.0.1
  42     Team runner name: lacp
  43 
  44 """
  45 
  46 import json
  47 import re
  48 from collections import OrderedDict
  49 from .. import parser, get_active_lines, LegacyItemAccess, CommandParser
  50 from insights.specs import Specs
  51 
  52 JSON_FIELDS = ["TEAM_CONFIG", "TEAM_PORT_CONFIG"]
  53 
  54 QUOTES = "\"'"
  55 
  56 bond_mode_map = {
  57     'balance-rr': 0,
  58     'active-backup': 1,
  59     'balance-xor': 2,
  60     'broadcast': 3,
  61     '802.3ad': 4,
  62     'balance-tlb': 5,
  63     'balance-alb': 6
  64 }
  65 
  66 
  67 @parser(Specs.ifcfg)
  68 class IfCFG(LegacyItemAccess, CommandParser):
  69     """
  70     Parse `ifcfg-` file,return a dict contain ifcfg config file info.
  71     "iface" key is interface name parse from file name
  72     `TEAM_CONFIG`, `TEAM_PORT_CONFIG` will return a dict with user config dict
  73     `BONDING_OPTS` also will return a dict
  74 
  75     Properties:
  76         ifname (str): The interface name as defined in the name of the file
  77             (i.e. the part after ``ifcfg-``).
  78     """
  79 
  80     def __init__(self, context):
  81         super(IfCFG, self).__init__(context)
  82         self.data["iface"] = context.path.rsplit("-", 1)[1]
  83         self.ifname = self.data['iface']
  84         self._has_empty_line = any(l.strip() == '' for l in context.content)
  85 
  86     def parse_content(self, content):
  87         self.data = {}
  88         for line in get_active_lines(content):
  89             if "=" not in line:
  90                 continue
  91             key, value = line.split("=", 1)
  92             # Since keys are variable names in bash, stripping quotes and
  93             # spaces off them makes no sense.
  94             key = key.strip().strip(QUOTES).upper()
  95 
  96             # In some cases we want to know what the actual value-side
  97             # of the key is before dequoting and stripping.
  98             if key in ["DEVICE", "MASTER", "BONDING_OPTS"]:
  99                 self.data["raw_{0}_value".format(key.split('_')[0].lower())] = value
  100             if key != "DEVICE":
  101                 value = value.strip().strip(QUOTES)
  102             if key in JSON_FIELDS:
  103                 value = json.loads(value.replace("\\", ""))
  104             if key == "BONDING_OPTS":
  105                 value_map = OrderedDict()
  106                 value = re.sub(r'\s*=\s*', '=', value)
  107                 for key_value_pair in value.split():
  108                     sub_key, sub_value = [
  109                         s.strip() for s in key_value_pair.split("=", 1)
  110                     ]
  111                     value_map[sub_key] = sub_value
  112                 value = value_map
  113             self.data[key] = value
  114 
  115     @property
  116     def bonding_mode(self):
  117         """
  118         (int) the numeric value of bonding mode, or `None` if no bonding
  119         mode is found.
  120         """
  121         if "BONDING_OPTS" not in self or 'mode' not in self['BONDING_OPTS']:
  122             return None
  123 
  124         m = self["BONDING_OPTS"]["mode"]
  125         if m.isdigit():
  126             return int(m)
  127         if m in bond_mode_map:
  128             return bond_mode_map[m]
  129         return None
  130 
  131     @property
  132     def has_empty_line(self):
  133         """
  134         (bool) `True` if the file has empty line else `False`.
  135         """
  136         return self._has_empty_line
  137
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/insights/parsers/ifcfg.py b/insights/parsers/ifcfg.py
  --- a/insights/parsers/ifcfg.py
  +++ b/insights/parsers/ifcfg.py
  @@ -95,7 +95,7 @@
   
               # In some cases we want to know what the actual value-side
               # of the key is before dequoting and stripping.
  -            if key in ["DEVICE", "MASTER", "BONDING_OPTS"]:
  +            if key in ["DEVICE", "MASTER", "TEAM_MASTER", "BONDING_OPTS"]:
                   self.data["raw_{0}_value".format(key.split('_')[0].lower())] = value
               if key != "DEVICE":
                   value = value.strip().strip(QUOTES)
  
verification_info: {"golden_diff": "diff --git a/insights/parsers/ifcfg.py b/insights/parsers/ifcfg.py\n--- a/insights/parsers/ifcfg.py\n+++ b/insights/parsers/ifcfg.py\n@@ -95,7 +95,7 @@\n \n             # In some cases we want to know what the actual value-side\n             # of the key is before dequoting and stripping.\n-            if key in [\"DEVICE\", \"MASTER\", \"BONDING_OPTS\"]:\n+            if key in [\"DEVICE\", \"MASTER\", \"TEAM_MASTER\", \"BONDING_OPTS\"]:\n                 self.data[\"raw_{0}_value\".format(key.split('_')[0].lower())] = value\n             if key != \"DEVICE\":\n                 value = value.strip().strip(QUOTES)\n", "issue": "ifcfg parser to support for MASTER and TEAM_MASTER keys slave type\nWe need to update the ifcfg parser to support TEAMING and BONDING slave type in the configuration file, so, that we can use MASTER' and 'TEAM_MASTER' keys in raw format.\r\n\r\nFor ex-  `obj['MASTER']=\"'bond0'\"` or `obj['TEAM_MASTER']=\"'team0'\"`\n", "before_files": [{"content": "\"\"\"\nIfCFG - files ``/etc/sysconfig/network-scripts/ifcfg-*``\n========================================================\n\nIfCFG is a parser for the network interface definition files in\n``/etc/sysconfig/network-scripts``.  These are pulled into the network\nscripts using ``source``, so they are mainly ``bash`` environment\ndeclarations of the form **KEY=value**.  These are stored in the ``data``\nproperty as a dictionary.  Quotes surrounding the value\n\nThree options are handled differently:\n\n* ``BONDING_OPTS`` is usually a quoted list of key=value arguments separated\n  by spaces.\n* ``TEAM_CONFIG`` and ``TEAM_PORT_CONFIG`` are treated as JSON stored as a\n  single string.  Double quotes within the string are escaped using double\n  back slashes, and these are removed so that the quoting is preserved.\n\nBecause this parser reads multiple files, the interfaces are stored as a\nlist within the parser and need to be iterated through in order to find\nspecific interfaces.\n\nSample configuration from a teamed interface in file ``/etc/sysconfig/network-scripts/ifcfg-team1``::\n\n    DEVICE=team1\n    DEVICETYPE=Team\n    ONBOOT=yes\n    NETMASK=255.255.252.0\n    IPADDR=192.168.0.1\n    TEAM_CONFIG='{\"runner\": {\"name\": \"lacp\", \"active\": \"true\", \"tx_hash\": [\"eth\", \"ipv4\"]}, \"tx_balancer\": {\"name\": \"basic\"}, \"link_watch\": {\"name\": \"ethtool\"}}'\n\nExamples:\n\n    >>> for nic in shared[IfCFG]: # Parser contains list of all interfaces\n    ...     print 'NIC:', nic.iname\n    ...     print 'IP address:', nic['IPADDR']\n    ...     if 'TEAM_CONFIG' in nic:\n    ...         print 'Team runner name:', nic['TEAM_CONFIG']['runner']['name']\n    ...\n    NIC: team1\n    IP addresss: 192.168.0.1\n    Team runner name: lacp\n\n\"\"\"\n\nimport json\nimport re\nfrom collections import OrderedDict\nfrom .. import parser, get_active_lines, LegacyItemAccess, CommandParser\nfrom insights.specs import Specs\n\nJSON_FIELDS = [\"TEAM_CONFIG\", \"TEAM_PORT_CONFIG\"]\n\nQUOTES = \"\\\"'\"\n\nbond_mode_map = {\n    'balance-rr': 0,\n    'active-backup': 1,\n    'balance-xor': 2,\n    'broadcast': 3,\n    '802.3ad': 4,\n    'balance-tlb': 5,\n    'balance-alb': 6\n}\n\n\n@parser(Specs.ifcfg)\nclass IfCFG(LegacyItemAccess, CommandParser):\n    \"\"\"\n    Parse `ifcfg-` file,return a dict contain ifcfg config file info.\n    \"iface\" key is interface name parse from file name\n    `TEAM_CONFIG`, `TEAM_PORT_CONFIG` will return a dict with user config dict\n    `BONDING_OPTS` also will return a dict\n\n    Properties:\n        ifname (str): The interface name as defined in the name of the file\n            (i.e. the part after ``ifcfg-``).\n    \"\"\"\n\n    def __init__(self, context):\n        super(IfCFG, self).__init__(context)\n        self.data[\"iface\"] = context.path.rsplit(\"-\", 1)[1]\n        self.ifname = self.data['iface']\n        self._has_empty_line = any(l.strip() == '' for l in context.content)\n\n    def parse_content(self, content):\n        self.data = {}\n        for line in get_active_lines(content):\n            if \"=\" not in line:\n                continue\n            key, value = line.split(\"=\", 1)\n            # Since keys are variable names in bash, stripping quotes and\n            # spaces off them makes no sense.\n            key = key.strip().strip(QUOTES).upper()\n\n            # In some cases we want to know what the actual value-side\n            # of the key is before dequoting and stripping.\n            if key in [\"DEVICE\", \"MASTER\", \"BONDING_OPTS\"]:\n                self.data[\"raw_{0}_value\".format(key.split('_')[0].lower())] = value\n            if key != \"DEVICE\":\n                value = value.strip().strip(QUOTES)\n            if key in JSON_FIELDS:\n                value = json.loads(value.replace(\"\\\\\", \"\"))\n            if key == \"BONDING_OPTS\":\n                value_map = OrderedDict()\n                value = re.sub(r'\\s*=\\s*', '=', value)\n                for key_value_pair in value.split():\n                    sub_key, sub_value = [\n                        s.strip() for s in key_value_pair.split(\"=\", 1)\n                    ]\n                    value_map[sub_key] = sub_value\n                value = value_map\n            self.data[key] = value\n\n    @property\n    def bonding_mode(self):\n        \"\"\"\n        (int) the numeric value of bonding mode, or `None` if no bonding\n        mode is found.\n        \"\"\"\n        if \"BONDING_OPTS\" not in self or 'mode' not in self['BONDING_OPTS']:\n            return None\n\n        m = self[\"BONDING_OPTS\"][\"mode\"]\n        if m.isdigit():\n            return int(m)\n        if m in bond_mode_map:\n            return bond_mode_map[m]\n        return None\n\n    @property\n    def has_empty_line(self):\n        \"\"\"\n        (bool) `True` if the file has empty line else `False`.\n        \"\"\"\n        return self._has_empty_line\n", "path": "insights/parsers/ifcfg.py"}], "after_files": [{"content": "\"\"\"\nIfCFG - files ``/etc/sysconfig/network-scripts/ifcfg-*``\n========================================================\n\nIfCFG is a parser for the network interface definition files in\n``/etc/sysconfig/network-scripts``.  These are pulled into the network\nscripts using ``source``, so they are mainly ``bash`` environment\ndeclarations of the form **KEY=value**.  These are stored in the ``data``\nproperty as a dictionary.  Quotes surrounding the value\n\nThree options are handled differently:\n\n* ``BONDING_OPTS`` is usually a quoted list of key=value arguments separated\n  by spaces.\n* ``TEAM_CONFIG`` and ``TEAM_PORT_CONFIG`` are treated as JSON stored as a\n  single string.  Double quotes within the string are escaped using double\n  back slashes, and these are removed so that the quoting is preserved.\n\nBecause this parser reads multiple files, the interfaces are stored as a\nlist within the parser and need to be iterated through in order to find\nspecific interfaces.\n\nSample configuration from a teamed interface in file ``/etc/sysconfig/network-scripts/ifcfg-team1``::\n\n    DEVICE=team1\n    DEVICETYPE=Team\n    ONBOOT=yes\n    NETMASK=255.255.252.0\n    IPADDR=192.168.0.1\n    TEAM_CONFIG='{\"runner\": {\"name\": \"lacp\", \"active\": \"true\", \"tx_hash\": [\"eth\", \"ipv4\"]}, \"tx_balancer\": {\"name\": \"basic\"}, \"link_watch\": {\"name\": \"ethtool\"}}'\n\nExamples:\n\n    >>> for nic in shared[IfCFG]: # Parser contains list of all interfaces\n    ...     print 'NIC:', nic.iname\n    ...     print 'IP address:', nic['IPADDR']\n    ...     if 'TEAM_CONFIG' in nic:\n    ...         print 'Team runner name:', nic['TEAM_CONFIG']['runner']['name']\n    ...\n    NIC: team1\n    IP addresss: 192.168.0.1\n    Team runner name: lacp\n\n\"\"\"\n\nimport json\nimport re\nfrom collections import OrderedDict\nfrom .. import parser, get_active_lines, LegacyItemAccess, CommandParser\nfrom insights.specs import Specs\n\nJSON_FIELDS = [\"TEAM_CONFIG\", \"TEAM_PORT_CONFIG\"]\n\nQUOTES = \"\\\"'\"\n\nbond_mode_map = {\n    'balance-rr': 0,\n    'active-backup': 1,\n    'balance-xor': 2,\n    'broadcast': 3,\n    '802.3ad': 4,\n    'balance-tlb': 5,\n    'balance-alb': 6\n}\n\n\n@parser(Specs.ifcfg)\nclass IfCFG(LegacyItemAccess, CommandParser):\n    \"\"\"\n    Parse `ifcfg-` file,return a dict contain ifcfg config file info.\n    \"iface\" key is interface name parse from file name\n    `TEAM_CONFIG`, `TEAM_PORT_CONFIG` will return a dict with user config dict\n    `BONDING_OPTS` also will return a dict\n\n    Properties:\n        ifname (str): The interface name as defined in the name of the file\n            (i.e. the part after ``ifcfg-``).\n    \"\"\"\n\n    def __init__(self, context):\n        super(IfCFG, self).__init__(context)\n        self.data[\"iface\"] = context.path.rsplit(\"-\", 1)[1]\n        self.ifname = self.data['iface']\n        self._has_empty_line = any(l.strip() == '' for l in context.content)\n\n    def parse_content(self, content):\n        self.data = {}\n        for line in get_active_lines(content):\n            if \"=\" not in line:\n                continue\n            key, value = line.split(\"=\", 1)\n            # Since keys are variable names in bash, stripping quotes and\n            # spaces off them makes no sense.\n            key = key.strip().strip(QUOTES).upper()\n\n            # In some cases we want to know what the actual value-side\n            # of the key is before dequoting and stripping.\n            if key in [\"DEVICE\", \"MASTER\", \"TEAM_MASTER\", \"BONDING_OPTS\"]:\n                self.data[\"raw_{0}_value\".format(key.split('_')[0].lower())] = value\n            if key != \"DEVICE\":\n                value = value.strip().strip(QUOTES)\n            if key in JSON_FIELDS:\n                value = json.loads(value.replace(\"\\\\\", \"\"))\n            if key == \"BONDING_OPTS\":\n                value_map = OrderedDict()\n                value = re.sub(r'\\s*=\\s*', '=', value)\n                for key_value_pair in value.split():\n                    sub_key, sub_value = [\n                        s.strip() for s in key_value_pair.split(\"=\", 1)\n                    ]\n                    value_map[sub_key] = sub_value\n                value = value_map\n            self.data[key] = value\n\n    @property\n    def bonding_mode(self):\n        \"\"\"\n        (int) the numeric value of bonding mode, or `None` if no bonding\n        mode is found.\n        \"\"\"\n        if \"BONDING_OPTS\" not in self or 'mode' not in self['BONDING_OPTS']:\n            return None\n\n        m = self[\"BONDING_OPTS\"][\"mode\"]\n        if m.isdigit():\n            return int(m)\n        if m in bond_mode_map:\n            return bond_mode_map[m]\n        return None\n\n    @property\n    def has_empty_line(self):\n        \"\"\"\n        (bool) `True` if the file has empty line else `False`.\n        \"\"\"\n        return self._has_empty_line\n", "path": "insights/parsers/ifcfg.py"}]}