HEX
Server: Apache
System: Linux srv13.cpanelhost.cl 3.10.0-962.3.2.lve1.5.38.el7.x86_64 #1 SMP Thu Jun 18 05:28:41 EDT 2020 x86_64
User: cca63905 (4205)
PHP: 7.3.20
Disabled: NONE
Upload Files
File: //lib/python2.7/site-packages/redhat_support_tool/plugins/list_cases.py
# -*- coding: utf-8 -*-

#
# Copyright (c) 2012 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#           http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from optparse import Option
from collections import deque
from redhat_support_lib.infrastructure.errors import RequestError, \
    ConnectionError
from redhat_support_tool.helpers.confighelper import _
from redhat_support_tool.helpers.confighelper import EmptyValueError
from redhat_support_tool.plugins import InteractivePlugin, ObjectDisplayOption
from redhat_support_tool.helpers.constants import Constants
from redhat_support_tool.helpers.launchhelper import LaunchHelper
from redhat_support_tool.plugins.get_case import GetCase
import pydoc
import redhat_support_tool.helpers.common as common
import redhat_support_tool.helpers.apihelper as apihelper
import redhat_support_tool.helpers.confighelper as confighelper
import logging

__author__ = 'Keith Robertson <kroberts@redhat.com>'
logger = logging.getLogger("redhat_support_tool.plugins.list_cases")


class ListCases(InteractivePlugin):
    plugin_name = 'listcases'
    ALL = _("Display all cases")
    partial_entries = _('%s of %s cases displayed. Type \'m\' to see more.')
    end_of_entries = _('No more cases to display')

    _submenu_opts = None
    _sections = None
    casesAry = None

    # Help should not print the option list
    help_is_options = False

    # Record the last offset value used with the API, and the maximum results
    # we should display for one search query.
    _nextOffset = 0
    _MAX_OFFSET = 1500  # From Strata devs

    @classmethod
    def get_usage(cls):
        '''
        The usage statement that will be printed by OptionParser.

        Example:
            - %prog -c CASENUMBER [options] <comment text here>
        Important: %prog is a OptionParser built-in.  Use it!
        '''
        return _('%prog')

    @classmethod
    def get_desc(cls):
        '''
        The description statement that will be printed by OptionParser.

        Example:
            - 'Use the \'%s\' command to add a comment to a case.'\
             % cls.plugin_name
        '''
        return _('Use the \'%s\' command to list your support cases.')\
             % cls.plugin_name

    @classmethod
    def get_epilog(cls):
        '''
        The epilog string that will be printed by OptionParser.  Usually
        used to print an example of how to use the program.

        Example:
         Examples:
          - %s -c 12345678 Lorem ipsum dolor sit amet, consectetur adipisicing
          - %s -c 12345678
        '''
        return _('Example:\n'
                 '  - %s\n'
                 '  - %s -o ownerSSOName\n'
                 '  - %s -o OwnerSSOName --includeclosed\n'
                 '  - %s -o ALL -k KEYWORD') % (cls.plugin_name,
                                                cls.plugin_name,
                                                cls.plugin_name,
                                                cls.plugin_name)

    @classmethod
    def get_options(cls):
        '''
        Subclasses that need command line options should override this method
        and return an array of optparse.Option(s) to be used by the
        OptionParser.

        Example:
         return [Option("-f", "--file", action="store",
                        dest="filename", help='Some file'),
                 Option("-c", "--case",
                        action="store", dest="casenumber",
                        help='A case')]

         Would produce the following:
         Command (? for help): help mycommand

         Usage: mycommand [options]

         Use the 'mycommand' command to find a knowledge base solution by ID
         Options:
           -h, --help  show this help message and exit
           -f, --file  Some file
           -c, --case  A case
         Example:
          - mycommand -c 12345 -f abc.txt

        '''
        return [Option('-c', '--includeclosed',
                       dest='includeclosed',
                       action='store_true',
                       help=_('Show closed cases. '
                              '(optional)'), default=False),
                Option('-o', '--owner', dest='owner',
                        help=_('Show cases belonging to a particular Red Hat '
                               'portal login ID. Default is show cases owned '
                               'by you. Use \'ALL\' to show all cases in '
                               'the account. (optional)'), default=None),
                Option('-g', '--casegroup', dest='casegroup',
                        help=_('Show cases only belonging to a particular '
                               'case group. (optional)'), default=None),
                Option('-k', '--keyword', dest='keyword',
                        help=_('Only show cases with the given keyword in '
                               'their title. (optional)'), default=None),
                Option('-u', '--ungrouped', dest='ungrouped',
                       action='store_true',
                       help=_('Include ungrouped cases in results. When this '
                              'is set case owner filters will be ignored.'
                              '(optional)'), default=False)]

    def _check_case_group(self):
        msg = _("ERROR: Invalid case group selection")
        if self._options['casegroup']:
            valid_groups = []
            given_groupAry = str(self._options['casegroup']).split(',')
            real_groupAry = common.get_groups()

            for i in given_groupAry:
                match = False
                for j in real_groupAry:
                    if i.lower() == j.get_name().lower():
                        valid_groups.append(j.get_number())
                        match = True
                if(not match):
                    msg = _("ERROR: Invalid case group(%s) specified." % i)
                    print msg
                    raise Exception(msg)

            if len(valid_groups) > 0:
                self._options['casegroupnumber'] = valid_groups

            logger.log(logging.INFO,
                       'Casegroup(%s) casegroupnumber(%s)' % (
                       given_groupAry,
                       self._options['casegroupnumber']))

    def _check_owner(self):
        if str(self._options['owner']).lower() == 'all' or self._options['ungrouped']:
            self._options['owner'] = None
        elif self._options['owner'] == None:
            cfg = confighelper.get_config_helper()
            user = cfg.get(section='RHHelp', option='user')
            self._options['owner'] = user

    def validate_args(self):
        self._check_case_group()
        self._check_owner()

    def get_intro_text(self):
        return _('\nType the number of the case to view or \'e\' '
                 'to return to the previous menu.')

    def get_prompt_text(self):
        return _('Select a Case: ')

    def get_sub_menu_options(self):
        return self._submenu_opts

    def get_more_options(self, num_options):
        if (len(self.casesAry) < self._nextOffset or
            len(self.casesAry) == 0 or
            self._nextOffset > self._MAX_OFFSET):
            # Either we did not max out on results last time, there were
            # no results last time, or we have seen more than _MAX_OFFSET
            # results.
            # In the instance of cases, the maximum a single query can
            # retrieve is 1500 cases, hence MAX_OFFSET is set to 1450
            return False

        # Strata introduces an issue where if the limit > 50, it will only
        # return 50 results. This creates a potential issue if the terminal
        # size is greater than 53.
        if num_options > 50:
            num_options = 50

        searchopts = {'count': num_options, 'start': self._nextOffset}
        self._nextOffset += num_options
        newresults = self._get_cases(searchopts)

        if len(newresults) == 0:
            return False

        self.casesAry.extend(newresults)
        self._parse_cases(newresults)
        return True

    def postinit(self):
        self._submenu_opts = deque()
        self._sections = {}

        searchopts = {'count': 50, 'start': 0}
        self.casesAry = self._get_cases(searchopts)
        self._nextOffset = 50

        try:
            if not self._parse_cases(self.casesAry):
                msg = _("Unable to find cases")
                print msg
                logger.log(logging.WARNING, msg)
                raise Exception()
        except:
            raise

    def non_interactive_action(self):
        doc = u''
        for opt in self._submenu_opts:
            if opt.display_text != self.ALL:
                doc += self._sections[opt]
        try:
            print doc.encode("UTF-8", 'replace')
        except Exception, e:
            # There are some truly bizarre errors when you pipe
            # the output from python's 'print' function with sys encoding
            # set to ascii. These errors seem to manifes when you pipe
            # to something like 'more' or 'less'.  You'll get encoding errors.
            # Curiously, you don't see them with 'grep' or even simply piping
            # to terminal.  WTF :(
            logger.log(logging.WARNING, e)
            import sys
            print doc.encode(sys.getdefaultencoding(),
                             'replace')

    def interactive_action(self, display_option=None):
        if display_option.display_text == self.ALL:
            doc = u''
            for opt in self._submenu_opts:
                if opt.display_text != self.ALL:
                    doc += self._sections[opt]
            pydoc.pipepager(doc.encode("UTF-8", 'replace'),
                            cmd='less -R')
        else:
            val = None
            try:
                val = display_option.stored_obj
                lh = LaunchHelper(GetCase)
                lh.run(val)
            except:
                raise Exception()

    def _parse_cases(self, cases_ary):
        '''
        Use this for non-interactive display of results.
        '''
        if len(cases_ary) == 0:
            return False

        try:
            doc = u''
            for val in cases_ary:
                doc += '%-12s %-60s\n' % ('%s:' % Constants.TITLE,
                                           val.get_summary())
                doc += '%-12s %-60s\n' % ('%s:' % Constants.CASE_NUMBER,
                                           val.get_caseNumber())
                doc += '%-12s %-60s\n' % (Constants.CASE_STATUS,
                                           val.get_status())
                vuri = val.get_view_uri()
                if vuri:
                    doc += '%-12s %-60s' % (Constants.URL, vuri)
                else:
                    doc += '%-12s %-60s' % (Constants.URL, val.get_uri())
                doc += '\n\n%s%s%s\n\n' % (Constants.BOLD,
                                           str('-' * Constants.MAX_RULE),
                                           Constants.END)
                disp_opt = ObjectDisplayOption('[' + val.get_status() + ']  ' +
                                         val.get_summary(),
                                         'interactive_action',
                                         val.get_caseNumber())
                self._submenu_opts.append(disp_opt)
                self._sections[disp_opt] = doc
        except:
            msg = _('ERROR: problem parsing the cases.')
            print msg
            logger.log(logging.WARNING, msg)
            return False
        return True

    def _get_cases(self, searchopts):
        api = None
        try:
            api = apihelper.get_api()
            if self._options['casegroup']:
                filt = api.im.makeCaseFilter(
                                count=searchopts['count'],
                                start=searchopts['start'],
                                includeClosed=self._options['includeclosed'],
                                groupNumbers=self._options['casegroupnumber'],
                                ownerSSOName=self._options['owner'],
                                keyword=self._options['keyword'],
                                onlyUngrouped=self._options['ungrouped'])
                return api.cases.filter(filt)

            else:
                filt = api.im.makeCaseFilter(
                                count=searchopts['count'],
                                start=searchopts['start'],
                                includeClosed=self._options['includeclosed'],
                                ownerSSOName=self._options['owner'],
                                keyword=self._options['keyword'],
                                onlyUngrouped=self._options['ungrouped'])
                return api.cases.filter(filt)

        except EmptyValueError, eve:
            msg = _('ERROR: %s') % str(eve)
            print msg
            logger.log(logging.WARNING, msg)
            raise
        except RequestError, re:
            msg = _('Unable to connect to support services API. '
                    'Reason: %s') % re.reason
            print msg
            logger.log(logging.WARNING, msg)
            raise
        except ConnectionError:
            msg = _('Problem connecting to the support services '
                    'API.  Is the service accessible from this host?')
            print msg
            logger.log(logging.WARNING, msg)
            raise
        except Exception:
            msg = _("Unable to find cases")
            print msg
            logger.log(logging.WARNING, msg)
            raise