docs: def extract(template_path, raw_text=None, raw_text_file=None, saltenv='base'):
      r'''
      Extracts the data entities from the unstructured
      raw text sent as input and returns the data
      mapping, processing using the TextFSM template.
  
      template_path
          The path to the TextFSM template.
          This can be specified using the absolute path
          to the file, or using one of the following URL schemes:
  
          - ``salt://``, to fetch the template from the Salt fileserver.
          - ``http://`` or ``https://``
          - ``ftp://``
          - ``s3://``
          - ``swift://``
  
      raw_text: ``None``
          The unstructured text to be parsed.
  
      raw_text_file: ``None``
          Text file to read, having the raw text to be parsed using the TextFSM template.
          Supports the same URL schemes as the ``template_path`` argument.
  
      saltenv: ``base``
          Salt fileserver envrionment from which to retrieve the file.
          Ignored if ``template_path`` is not a ``salt://`` URL.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' textfsm.extract salt://textfsm/juniper_version_template raw_text_file=s3://junos_ver.txt
          salt '*' textfsm.extract http://some-server/textfsm/juniper_version_template raw_text='Hostname: router.abc ... snip ...'
  
      Jinja template example:
  
      .. code-block:: jinja
  
          {%- set raw_text = 'Hostname: router.abc ... snip ...' -%}
          {%- set textfsm_extract = salt.textfsm.extract('https://some-server/textfsm/juniper_version_template', raw_text) -%}
  
      Raw text example:
  
      .. code-block:: text
  
          Hostname: router.abc
          Model: mx960
          JUNOS Base OS boot [9.1S3.5]
          JUNOS Base OS Software Suite [9.1S3.5]
          JUNOS Kernel Software Suite [9.1S3.5]
          JUNOS Crypto Software Suite [9.1S3.5]
          JUNOS Packet Forwarding Engine Support (M/T Common) [9.1S3.5]
          JUNOS Packet Forwarding Engine Support (MX Common) [9.1S3.5]
          JUNOS Online Documentation [9.1S3.5]
          JUNOS Routing Software Suite [9.1S3.5]
  
      TextFSM Example:
  
      .. code-block:: text
  
          Value Chassis (\S+)
          Value Required Model (\S+)
          Value Boot (.*)
          Value Base (.*)
          Value Kernel (.*)
          Value Crypto (.*)
          Value Documentation (.*)
          Value Routing (.*)
  
          Start
          # Support multiple chassis systems.
            ^\S+:$$ -> Continue.Record
            ^${Chassis}:$$
            ^Model: ${Model}
            ^JUNOS Base OS boot \[${Boot}\]
            ^JUNOS Software Release \[${Base}\]
            ^JUNOS Base OS Software Suite \[${Base}\]
            ^JUNOS Kernel Software Suite \[${Kernel}\]
            ^JUNOS Crypto Software Suite \[${Crypto}\]
            ^JUNOS Online Documentation \[${Documentation}\]
            ^JUNOS Routing Software Suite \[${Routing}\]
  
      Output example:
  
      .. code-block:: json
  
          {
              "comment": "",
              "result": true,
              "out": [
                  {
                      "kernel": "9.1S3.5",
                      "documentation": "9.1S3.5",
                      "boot": "9.1S3.5",
                      "crypto": "9.1S3.5",
                      "chassis": "",
                      "routing": "9.1S3.5",
                      "base": "9.1S3.5",
                      "model": "mx960"
                  }
              ]
          }
      '''
      ret = {
          'result': False,
          'comment': '',
          'out': None
      }
      log.debug('Using the saltenv: %s', saltenv)
      log.debug('Caching %s using the Salt fileserver', template_path)
      tpl_cached_path = __salt__['cp.cache_file'](template_path, saltenv=saltenv)
      if tpl_cached_path is False:
          ret['comment'] = 'Unable to read the TextFSM template from {}'.format(template_path)
          log.error(ret['comment'])
          return ret
      try:
          log.debug('Reading TextFSM template from cache path: %s', tpl_cached_path)
          # Disabling pylint W8470 to nto complain about fopen.
          # Unfortunately textFSM needs the file handle rather than the content...
          # pylint: disable=W8470
          tpl_file_handle = fopen(tpl_cached_path, 'r')
          # pylint: disable=W8470
          log.debug(tpl_file_handle.read())
          tpl_file_handle.seek(0)  # move the object position back at the top of the file
          fsm_handler = textfsm.TextFSM(tpl_file_handle)
      except textfsm.TextFSMTemplateError as tfte:
          log.error('Unable to parse the TextFSM template', exc_info=True)
          ret['comment'] = 'Unable to parse the TextFSM template from {}: {}. Please check the logs.'.format(
              template_path, tfte)
          return ret
      if not raw_text and raw_text_file:
          log.debug('Trying to read the raw input from %s', raw_text_file)
          raw_text = __salt__['cp.get_file_str'](raw_text_file, saltenv=saltenv)
          if raw_text is False:
              ret['comment'] = 'Unable to read from {}. Please specify a valid input file or text.'.format(raw_text_file)
              log.error(ret['comment'])
              return ret
      if not raw_text:
          ret['comment'] = 'Please specify a valid input file or text.'
          log.error(ret['comment'])
          return ret
      log.debug('Processing the raw text:')
      log.debug(raw_text)
      objects = fsm_handler.ParseText(raw_text)
      ret['out'] = _clitable_to_dict(objects, fsm_handler)
      ret['result'] = True
      return ret