def add_connection(self) -> Optional[JenkinsConnection]:
        print('Enter a name for this connection, or enter nothing to exit.')
        connection_name = get_input('>', lowered=False)
        if connection_name:
            print('Enter a Jenkins base url.')
            print('Example: http://cassci.datastax.com/')
            url = get_input('>')

            auth = {}
            is_auth = is_yes('Does this connection require authentication?')
            if is_auth:
                auth['username'] = get_input(
                    'Please enter connection username\n', lowered=False)
                print('Please enter connection password')
                auth['password'] = getpass()

            try:
                jenkins_connection = JenkinsConnection(connection_name, url,
                                                       auth)
                self.jenkins_connections[
                    jenkins_connection.name] = jenkins_connection
                self.save_jenkins_config()
                print('Successfully added connection: {}'.format(
                    connection_name))
                pause()
                return jenkins_connection
            except (HTTPError, MissingSchema, ConnectionError) as e:
                print('Error occurred adding new connection: {}'.format(e))
                print('Invalid Jenkins URL. Please try again.')
                pause()
        return None
Exemple #2
0
 def add_organization(self) -> None:
     while True:
         if len(self._organizations.keys()) != 0:
             print('Known organizations:')
         for known_org in self._organizations.keys():
             print('   {}'.format(known_org))
         org_name = get_input('Enter a new org name, [q] to quit:', False)
         if org_name == 'q':
             break
         new_org = set()  # type: Set[str]
         while True:
             clear()
             print('Org: {}'.format(org_name))
             for team_name in new_org:
                 print('   {}'.format(team_name))
             choice = get_input('[a]dd a new team to this org, [q]uit')
             if choice == 'q':
                 break
             elif choice == 'a':
                 new_team = self.pick_team(list(new_org))
                 if new_team is not None:
                     new_org.add(new_team.name)
             else:
                 print('Bad choice. Try again.')
                 pause()
         if new_org is not None:
             self._organizations[org_name] = new_org
             self._save_config()
             print('New org {} added.'.format(org_name))
             break
Exemple #3
0
    def edit_team(self, team_manager):
        if len(self._teams) > 0:
            print('Currently contained teams:')
            for t in list(self._teams.keys()):
                team = self._teams[t]
                print('   Name: {}'.format(team.name))
                print('      Assignees: {}'.format(','.join(team.members)))

        cmd = get_input('[A]dd a team, [R]emove a team, or [Q]uit?')
        if cmd == 'q':
            return
        elif cmd == 'a':
            if 'assignee' in self._jira_filters or 'reviewer' in self._jira_filters or 'reviewer2' in self._jira_filters:
                conf = get_input(
                    'Adding a team will remove all active assignee or reviewer filters. Are you sure?'
                )
                if conf == 'n':
                    return
                del self._jira_filters['assignee']
                del self._jira_filters['reviewer']
                del self._jira_filters['reviewer2']
            to_add = team_manager.pick_team()
            if to_add is None:
                return
            self._teams[to_add.name] = to_add
        elif cmd == 'r':
            tr = pick_value('Remove which team?', list(self._teams.keys()),
                            True, 'Cancel')
            if tr is None:
                return
            conf = get_input('About to delete {}. Are you sure?'.format(tr))
            if conf == 'y':
                del self._teams[tr]
 def add_label_view(self):
     name = get_input('Name this view: ')
     jira_connection_name = pick_value(
         'Which JIRA Connection does this belong to? ',
         list(self._jira_connections.keys()))
     jira_connection = self._jira_connections[jira_connection_name]
     new_view = JiraView(name, jira_connection)
     self.jira_views[name] = new_view
     jira_filter = JiraFilter('labels', jira_connection)
     while True:
         label = get_input('Add which label? ([q] to quit)')
         if label == 'q':
             break
         if label.isspace() or label == '':
             continue
         print('Adding label: [{}]'.format(label))
         jira_filter.include(label)
     res_jf = JiraFilter('Resolution', jira_connection)
     res_jf.include('unresolved')
     new_view.add_raw_filter(jira_filter)
     new_view.add_raw_filter(res_jf)
     self._save_config()
     new_view.display_view(self)
     print('Creating new view with label(s): {}'.format(','.join(
         jira_filter._includes)))
    def search_projects(self):
        """
        Does a one-off ad-hoc search for strings in all cached fields for all cached JiraProjects.
        Keeping at scope of JiraManager as search is a meta-scoped search of all cached JiraProjects independent of JiraConnection
        :return:
        """
        tinput = get_input('Search [o]pen issues only, [c]losed, or [a]ll?')
        substring = get_input('Search for what substring?')
        matches = []
        jira_projects = self.get_all_cached_jira_projects()

        # cache list of seen columns for the query
        columns = {}
        for project in list(jira_projects.values()):
            results = project.get_matching_issues(substring, tinput)
            for r in results:
                matches.append(r)
                for k, v in r.items():
                    # This is going to blast out our ability to filter on reviewer or reviewer 2. For now.
                    if 'custom' not in k:
                        columns[k] = True
        original_list = JiraUtils.sort_custom_jiraissues_by_key(matches)
        display_list = original_list

        df = DisplayFilter.default()
        while True:
            df.display_and_return_sorted_issues(self, display_list)
            print_separator(30)
            cinput = get_input(
                '[#] to open an issue in browser, [c] to clear column filters, [f] to specify a specific field to match on, [q] to return to menu:'
            )
            if str.lower(cinput) == 'f':
                col_name = pick_value('Filter on which column?',
                                      list(columns.keys()), False)
                newlist = []
                for ji in display_list:
                    if col_name in ji:
                        if substring in ji[col_name]:
                            newlist.append(ji)
                display_list = newlist
            elif str.lower(cinput) == 'c':
                display_list = original_list
            elif not str.lower(cinput) == 'q':
                try:
                    jira_issue = display_list[int(cinput) - 1]
                    JiraUtils.open_issue_in_browser(
                        self._jira_connections[
                            jira_issue.jira_connection_name].url,
                        jira_issue.issue_key)
                except ValueError:
                    print('Bad input. Try again.')
            elif str.lower(cinput) == 'q':
                break
    def edit_team(self, jira_manager, team_name=None):
        # type: (JiraManager, str) -> None
        if team_name is None:
            team_name = pick_value('Edit which team?',
                                   list(self._teams.keys()), True, 'Cancel')
            if team_name is None:
                return None

        team = self._teams[team_name]
        jira_connection = jira_manager.get_jira_connection(
            team.jira_connection_name)

        while True:
            clear()
            print('-------------------------')
            print('[Edit {}]'.format(team))
            print('-------------------------')
            cmd = get_input(
                '[A]dd more members, [R]emove a member, or [Q]uit?')
            if cmd == 'a':
                assignees = jira_connection.pick_assignees(sys.maxsize)
                if assignees is None or len(assignees) == 0:
                    print('No assignees chosen. Returning.')
                    return None
                for assignee in assignees:
                    if assignee in team.member_names:
                        print(
                            'Assignee already exists in {}. Skipping.'.format(
                                team.name))
                        continue
                    else:
                        team.add_member(assignee, jira_connection)
                        print('Added {} to {}.'.format(assignee, team.name))
                        self._save_config()
            elif cmd == 'r':
                assignee = pick_value('Remove which assignee?',
                                      team.member_names, True, 'Cancel')
                if assignee is None:
                    continue
                confirm = get_input('Delete {} from {}: Are you sure?'.format(
                    assignee, team.name))
                if confirm == 'y':
                    team.delete_member(assignee)
            elif cmd == 'q':
                break
            else:
                print('Bad input. Valid input: A, R, or Q.')
                pause()
        self._save_config()
    def print_job_options(self, jobs, connection=False):
        # type: (List[JenkinsJob], bool) -> None
        # this is a terrible way of doing this
        sorted_jobs = JenkinsConnection.sort_jobs(jobs)
        if connection:
            self.active_connection.print_job_report(sorted_jobs)
        else:
            self.active_report.print_report(sorted_jobs)

        while True:
            print('Options:')
            print('Enter [#] to print test report for that job.')
            print('Enter [p] to re-print job report.')
            print('Enter [q] to exit.')
            selection = get_input('>')
            if selection.isdigit() and int(selection) in range(
                    len(sorted_jobs)):
                jenkins_job = sorted_jobs[int(selection)]
                tests = jenkins_job.jenkins_tests
                self.print_test_options(tests)
                if connection:
                    self.active_connection.print_job_report(sorted_jobs)
                else:
                    self.active_report.print_report(sorted_jobs)
            elif selection == 'q':
                break
            elif selection == 'p':
                sorted_jobs = JenkinsConnection.sort_jobs(jobs)
                if connection:
                    JenkinsConnection.print_job_report(sorted_jobs)
                else:
                    self.active_report.print_report(sorted_jobs)
            else:
                print('Invalid selection, please try again.')
Exemple #8
0
    def edit_view(self, team_manager, jira_manager):
        # type: (TeamManager, JiraManager) -> None
        print('Current view contents: {}'.format(self))

        while True:
            print_separator(40)
            print('-  JiraView Menu: {}'.format(self.name))
            print_separator(40)
            print('a: Add a filter on View')
            print('r: Remove a filter on a JiraView')
            print('t: Edit teams in View')
            print('d: Display issues matching this view.')
            print('q: Return to previous menu')
            print_separator(40)
            choice = get_input(':')
            if choice == 'q':
                return
            elif choice == 't':
                self.edit_team(team_manager)
            elif choice == 'a':
                self.add_filter()
            elif choice == 'r':
                self.remove_filter()
            elif choice == 'd':
                self.display_view(jira_manager)
Exemple #9
0
 def _display_readme(self):
     while True:
         print('======================================')
         print(' How To Use Argus ')
         print('======================================')
         clear()
         fn = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                           'readme.md')
         in_user_guide = False
         with open(fn, "r") as myfile:
             for line in myfile:
                 if "<!-- start_user_guide -->" in line:
                     in_user_guide = True
                     line = line.replace('<!-- start_user_guide -->', '')
                     print(line)
                 elif in_user_guide:
                     if "<!-- end_user_guide -->" not in line:
                         print(line)
                     else:
                         in_user_guide = False
                         line = line.replace('<!-- end_user_guide -->', '')
                         print(line)
         i = get_input('[q] to quit.')
         if i == 'q':
             break
Exemple #10
0
    def display(self) -> None:
        while True:
            clear()
            print(thick_separator)
            print('Argus - {}'.format(self.menu_header))
            print(thick_separator)

            for menu_option in self.active_menu:
                # Menu header
                if menu_option.hotkey is None:
                    print('')
                else:
                    print('{:2}: {foo}'.format(menu_option.hotkey,
                                               foo=menu_option.entry_name))
            print(thin_separator)

            c_input = get_input('>')

            # brute force ftw.
            for menu_option in self.active_menu:
                if c_input == menu_option.hotkey:
                    if menu_option.entry_method is not None:
                        menu_option.entry_method()
                    if menu_option.needs_pause:
                        pause()
Exemple #11
0
    def display_escalations(self):
        jira_connection_name = pick_value(
            'Select a JIRA Connection to view Escalation type tickets:',
            list(self._jira_connections.keys()))
        jira_connection = self._jira_connections[jira_connection_name]
        jira_issues = JiraUtils.get_issues_by_query(
            jira_connection,
            'type = \'Escalation\' AND resolution = unresolved')
        issue_keys = []
        for issue in jira_issues:
            issue_keys.append(issue.issue_key)

        df = DisplayFilter.default()
        while True:
            print_separator(30)
            print(os.linesep + 'Escalations' + os.linesep)
            print_separator(30)
            clear()
            df.display_and_return_sorted_issues(self, jira_issues)
            i = get_input('[#] Integer to open issue in browser. [q] to quit.')
            if i == 'q':
                break
            try:
                c_input = int(i) - 1
                JiraUtils.open_issue_in_browser(jira_connection.url,
                                                issue_keys[c_input])
            except ValueError:
                print('Bad input. Try again')
                pause()
Exemple #12
0
    def add_filter(self):
        filter_value = None
        # Adding to prevent PEP complaint.
        filter_name = None
        while filter_value is None:
            filters = JiraView.PRE_FILTERS[:]
            filters.append('Remove a filter')
            filters.append('Other')
            filter_name = pick_value('Select a field to filter on:', filters,
                                     True, 'Cancel view edit')
            if filter_name is None:
                return

            # Special logic to handle things we have known values for
            if filter_name in self._known_fields:
                filter_value = pick_value('Select {}'.format(filter_name),
                                          self._known_fields[filter_name])
            # since potential assignees vary by project, we don't store them in _known_fields
            elif filter_name == 'assignee' or filter_name == 'reviewer' or filter_name == 'reviewer2' or filter_name == 'reporter':
                # Disallow addition of assignee/reviewer/reviewer2 if a team filter is active
                if len(self._teams) > 0:
                    if filter_name != 'reporter':
                        print(
                            'Cannot add a[n] {} filter when a team filter is active. Remove team filter if you would like to add this.'
                            .format(filter_name))
                        return
                filter_value = self.jira_connection.pick_single_assignee()
                if filter_value is None:
                    return
            elif filter_name == 'Project':
                filter_value = self.jira_connection.pick_project()
                if filter_value is None:
                    return
            elif filter_name == 'Remove a filter':
                self.remove_filter()
                return
            else:
                filter_value = get_input('{}:'.format(filter_name))

        while True:
            filter_type = get_input('[i]nclude or [e]xclude?')
            if not filter_type == 'i' and not filter_type == 'e':
                print('Try again.')
            else:
                break

        self.add_single_filter(filter_name, filter_value, filter_type, 'AND')
Exemple #13
0
    def prompt_for_team_addition(self, jira_manager: 'JiraManager') -> None:
        name = get_input('Name this new team:', lowered=False)

        jira_connection_name = pick_value('Which JIRA Connection owns this team?', jira_manager.possible_connections(), True, 'Cancel')
        if jira_connection_name is None:
            return
        self._teams[name] = Team(name, jira_connection_name)
        self.edit_team(jira_manager, name)
 def on_input_requested():
     while not interpreter.output.empty():
         draw_instructions(interpreter, arcade_screen)
     if interactive:
         arcade_screen.render()
         int_input = get_input()
     else:
         int_input = player.act()
     interpreter.input.put(int_input)
Exemple #15
0
 def remove_dashboard(self):
     dn = pick_value('Remove which dashboard?',
                     list(self.jira_dashboards.keys()), True, 'Cancel')
     if dn is None:
         return
     prompt = get_input('About to delete [{}]. Are you sure?'.format(dn))
     if prompt == 'y':
         del self.jira_dashboards[dn]
         self._save_config()
Exemple #16
0
    def display_view(self, jira_manager: 'JiraManager') -> None:
        df = DisplayFilter.default()

        working_issues = list(self.get_issues().values())
        while True:
            try:
                issues = df.display_and_return_sorted_issues(
                    jira_manager, working_issues)
                print_separator(60)
                print('[JiraView operations for {}]'.format(self.name))
                input_prompt = (
                    "[f] to manually enter a substring to regex issues in the view\n"
                    "[c] to clear all regex filtering\n"
                    "[#] Integer value to open ticket in browser\n"
                    "[q] to quit\n"
                    ":")
                custom = get_input(input_prompt)
                if custom == 'q':
                    return
                elif custom == 'f':
                    string = get_input('substring to match:', lowered=False)
                    new_issues = []
                    for jira_issue in working_issues:
                        if jira_issue.matches(self.jira_connection, string):
                            new_issues.append(jira_issue)
                    working_issues = new_issues
                elif custom == 'c':
                    working_issues = list(self.get_issues().values())
                elif len(issues) == 0:
                    print(
                        'No matching jira issues found. Skipping attempt to open.'
                    )
                    pause()
                else:
                    try:
                        JiraUtils.open_issue_in_browser(
                            self.jira_connection.url,
                            issues[int(custom) - 1].issue_key)
                    except ValueError:
                        print('Bad input. Try again.')
            except JIRAError as je:
                print('Caught an error: {}'.format(je))
                traceback.print_exc()
                return
Exemple #17
0
    def add_connection(
            self,
            prompt: str = 'Name this connection:') -> Optional[JiraConnection]:
        """
        Swallows exceptions to allow for errors during JiraProject caching w/out invalidating addition of JiraConnection
        """
        connection_name = get_input(prompt)
        if is_empty(connection_name):
            return None

        url = get_input(
            'JIRA url (example: http://issues.apache.org/jira/):').rstrip('/')
        if is_empty(url):
            return None

        user = get_input('JIRA user name:')
        if is_empty(user):
            return None

        password = getpass.getpass()

        new_jira_connection = JiraConnection(connection_name, url, user,
                                             password)
        self._jira_connections[
            new_jira_connection.connection_name] = new_jira_connection

        print(
            'Must locally cache at least one project\'s JIRA history. Please select a project.'
        )
        new_jira_connection.cache_new_jira_project(self)
        try:
            while True:
                if not is_yes('Add another project?'):
                    break
                new_jira_connection.cache_new_jira_project(self)
        except (JIRAError, IOError):
            print(
                'Encountered exception processing JiraProjects. Saving base JiraConnection'
            )
            traceback.print_exc()

        self._save_config()
        return new_jira_connection
    def download_jobs(self):
        download_method = pick_value(
            'Would you like to download jobs by view or individually?',
            ['By View', 'Individually'],
            sort=False)
        if download_method:
            if download_method == 'By View':
                if self.active_connection.jenkins_views:
                    view_options = self.active_connection.view_names
                    all_views = '* All Views'
                    view_options.append(all_views)
                    view_name = pick_value(
                        'Which saved view would you like to download jobs for?',
                        view_options)
                    if view_name:
                        if view_name == all_views:
                            self.active_connection.download_jobs()
                            self.active_connection.save_job_data()
                            print(
                                'Successfully downloaded jobs for all views.')
                            pause()
                        else:
                            self.active_connection.download_jobs(view_name)
                            self.active_connection.save_job_data()
                            print('Successfully downloaded jobs for view: {}'.
                                  format(view_name))
                            pause()
                else:
                    if is_yes(
                            'No Jenkins views. Would you like to add one now?'
                    ):
                        self.add_view()
                        view_name = self.active_connection.view_names[0]
                        if is_yes('Download jobs for this view?'):
                            self.active_connection.download_jobs(view_name)
                            self.active_connection.save_job_data()
                            print('Successfully downloaded jobs for view: {}'.
                                  format(view_name))
                            pause()

            elif download_method == 'Individually':
                job_name = get_input(
                    'Enter the exact, case-sensitive name of the job, or enter nothing to exit.\n>',
                    lowered=False)
                if job_name:
                    if self.active_connection.download_single_job(job_name):
                        self.active_connection.save_job_data()
                        print('Successfully downloaded Jenkins job: {}'.format(
                            job_name))
                        pause()
                    else:
                        print('Failed to download Jenkins job: {}'.format(
                            job_name))
                        pause()
Exemple #19
0
    def run_org_report(self, jira_manager: 'JiraManager') -> None:
        """
        Sub-menu driven method to run a specific type of report across multiple teams within an organization
        """
        org_name = None

        if len(self._organizations) == 0:
            # We don't prompt for addition now since we'd have to pass in main menu context to do that from here.
            print('No organizations found. Please use the Team Management menu to define a new organization before running a report.')
            pause()
            return

        while True:
            clear()
            if org_name is None:
                print_separator(40)
                org_name = pick_value('Run reports against which organization?', list(self._organizations.keys()))
                # None return from pick_team == cancel
                if org_name is None:
                    return
                for team_name in sorted(self._organizations[org_name]):
                    active_team = self._teams[team_name]
                    print('Populating tickets for team: {}'.format(active_team.name))
                    TeamManager.populate_owned_jira_issues(jira_manager, active_team.members)

            print('---------------------')
            print('-    Org Menu      -')
            print('---------------------')
            print('t: Change active org. Current: {}'.format(org_name))
            self._print_report_menu()
            print('q: Cancel')
            print('---------------------')
            choice = get_input(':')
            if choice == 'q':
                return
            elif choice == 't':
                org_name = None
            try:
                report_type = ReportType.from_int(int(choice))
                if report_type == ReportType.UNKNOWN:
                    print('Bad input: {}. Try again.'.format(choice))
                    pause()
                else:
                    report_to_run = TeamManager.reports[report_type]
                    if TeamManager.reports[report_type].needs_duration:
                        report_to_run.since = time_utils.since_now(ReportFilter.get_since())
                    # making mypy happy
                    assert org_name is not None
                    self._run_org_report(jira_manager, org_name, report_to_run)
                    pause()
            except (ValueError, TypeError) as e:
                print('Error on input: {}. Try again'.format(e))
                traceback.print_exc()
                pause()
Exemple #20
0
    def display_view(self, jira_manager):
        # type: (JiraManager) -> None
        df = DisplayFilter.default()

        working_issues = list(self.get_issues().values())
        while True:
            try:
                issues = df.display_and_return_sorted_issues(
                    jira_manager, working_issues)
                print_separator(60)
                print('[JiraView operations for {}]'.format(self.name))
                custom = get_input(
                    '[f] to manually enter a substring to regex issues in the view'
                    + os.linesep + '[c] to clear all regex filtering' +
                    os.linesep +
                    '[#] Integer value to open ticket in browser ' +
                    os.linesep + '[q] to quit' + os.linesep + ':')
                if custom == 'q':
                    return
                elif custom == 'f':
                    string = get_input('substring to match:', lowered=False)
                    new_issues = []
                    for jira_issue in working_issues:
                        if jira_issue.matches(self.jira_connection, string):
                            new_issues.append(jira_issue)
                    working_issues = new_issues
                elif custom == 'c':
                    working_issues = list(self.get_issues().values())
                else:
                    try:
                        JiraUtils.open_issue_in_browser(
                            self.jira_connection.url,
                            issues[int(custom) - 1].issue_key)
                    except ValueError:
                        print('Bad input. Try again.')
            except JIRAError as je:
                print('Caught an error: {}'.format(je))
                traceback.print_exc()
                return
 def add_custom_report(self):
     report_name = get_input(
         'Enter a name for this custom report, or enter nothing to exit.\n>',
         lowered=False)
     if report_name:
         report = JenkinsReport(report_name)
         report.save_report_config()
         self.jenkins_reports[report_name] = report
         self.save_jenkins_config()
         print('Successfully added custom report: {}'.format(report_name))
         pause()
         self.active_report = self.get_custom_report(report_name)
         self._main_menu.go_to_jenkins_report_menu()
Exemple #22
0
 def remove_filter(self) -> None:
     print('Removing from JiraFilter: {}'.format(self))
     action = get_input('Remove [i]nclude, [e]xclude, or [q]uit')
     if action == 'i':
         to_remove = pick_value('Remove which include?', self._includes)
         if to_remove is None:
             return
         self._includes.remove(to_remove)
     elif action == 'e':
         to_remove = pick_value('Remove which exclude?', self._excludes)
         if to_remove is None:
             return
         self._excludes.remove(to_remove)
Exemple #23
0
def setup_aws():
    home_path = path.expanduser('~')
    aws_dir_path = ''.join([home_path, '/.aws'])
    aws_cred_path = ''.join([home_path, '/.aws/credentials'])
    aws_conf_path = ''.join([home_path, '/.aws/config'])
    if not path.exists(aws_dir_path):
        mkdir(aws_dir_path)

    with open(aws_cred_path, 'w') as cred:
        with open(aws_conf_path, 'w') as conf:
            aws_key = get_input('enter aws access key id: ',
                                lambda x: len(x) == 20)
            aws_secret = get_input('enter aws secret access key: ',
                                   lambda x: len(x) == 40)

            cred.writelines([
                f'[default]\n', f'aws_access_key_id = {aws_key}\n',
                f'aws_secret_access_key = {aws_secret}\n'
            ])

            conf.writelines([f'[default]\n', f'region = eu-west-1\n'])

            cred.close()
            conf.close()
    def print_test_options(tests):
        sorted_tests = JenkinsConnection.sort_tests(tests)
        JenkinsConnection.print_test_report(sorted_tests)

        while True:
            print('Options:')
            print('Enter [p] to re-print test report.')
            print('Enter [q] to exit.')
            selection = get_input('>')
            if selection == 'q':
                break
            elif selection == 'p':
                sorted_tests = JenkinsConnection.sort_tests(tests)
                JenkinsConnection.print_test_report(sorted_tests)
            else:
                print('Invalid selection, please try again.')
Exemple #25
0
    def run_team_reports(self, jira_manager: 'JiraManager') -> None:
        """
        Sub-menu driven method to run some specific reports of interest against teams. This will take into account
        linked members and run the report for all tickets across multiple JIRA connections.
        """
        selected_team = None

        if len(self._teams) == 0:
            # We don't prompt for addition now since we'd have to pass in main menu context to do that from here.
            print('No teams found. Please use the Team Management menu to define a new team before running a report.')
            pause()
            return

        while True:
            clear()
            if selected_team is None:
                print('No active team. Please select a team:')
                selected_team = self.pick_team()
                # None return from pick_team == cancel
                if selected_team is None:
                    return
                TeamManager.populate_owned_jira_issues(jira_manager, selected_team.members)

            print('---------------------')
            print('-    Team Menu      -')
            print('---------------------')
            print('t: Change active root team. Current: {}'.format(selected_team.name))
            self._print_report_menu()
            print('q: Cancel')
            print('---------------------')
            choice = get_input(':')
            if choice == 'q':
                return
            elif choice == 't':
                selected_team = None
            try:
                report_type = ReportType.from_int(int(choice))
                if report_type == ReportType.UNKNOWN:
                    print('Bad input: {}. Try again.'.format(choice))
                    pause()
                else:
                    assert selected_team is not None
                    TeamManager._run_report(jira_manager, selected_team, TeamManager.reports[report_type])
            except (ValueError, TypeError) as e:
                print('Error on input: {}. Try again'.format(e))
                traceback.print_exc()
                pause()
Exemple #26
0
    def _run_org_report(self, jira_manager: 'JiraManager', org_name: str, report_filter: ReportFilter) -> None:
        """
        Spins within a menu to pull up details on individuals.
        """
        while True:
            # Print out a menu of the meta information for this report
            print_separator(40)
            report_filter.print_description()
            print_separator(40)
            print('Report for org: {}'.format(org_name))
            print('[{}]'.format(report_filter.header))

            count = 1
            # Store displayed order at top level, sorted on per-team basis
            meta_sorted_issues = []
            for team_name in self._organizations[org_name]:
                print_separator(30)
                print('[Team: {}]'.format(team_name))
                print(report_filter.column_headers())
                team_members = self._teams[team_name].members
                sorted_members = sorted(team_members, key=lambda s: s.primary_name.user_name)
                meta_sorted_issues.extend(sorted_members)

                # Display in sorted order per team.
                for member_issues in sorted_members:
                    report_filter.clear()
                    # We perform pre-processing and one-off prompting for time duration in .process call
                    report_filter.process_issues(member_issues)
                    print('{:5}: {}'.format(count, report_filter.print_all_counts(member_issues.primary_name.user_name)))
                    count += 1

            selection = get_input('[#] to open details for a team member, [q] to return to previous menu')
            if selection == 'q':
                break
            int_sel = as_int(selection)
            if int_sel is None:
                continue

            # 0 indexed on List
            int_sel -= 1
            if int_sel > len(meta_sorted_issues) or int_sel < 0:
                print('Bad value.')
                continue
            tickets = meta_sorted_issues[int_sel]
            TeamManager._print_member_details(jira_manager, tickets, report_filter)
Exemple #27
0
 def edit_view(self) -> None:
     if len(self.jira_views) == 0:
         if is_yes('No views to edit. Would you like to add a view?'):
             self.add_view()
         else:
             return
     view_name = pick_value('Select a view to edit',
                            list(self.jira_views.keys()))
     if view_name is None:
         return
     view = self.jira_views[view_name]
     view.edit_view(self, self.team_manager)
     if view.is_empty():
         print('Jira View is empty. Remove it?')
         conf = get_input('Jira View is empty. Remove it? (q to cancel):')
         if conf == 'y':
             del self.jira_views[view_name]
     self._save_config()
Exemple #28
0
    def _run_report(jira_manager: 'JiraManager', team: Team, report_filter: ReportFilter) -> None:
        # We prompt for a new 'since' on each iteration of the loop in non-org reporting
        if report_filter.needs_duration:
            report_filter.since = time_utils.since_now(ReportFilter.get_since())

        report_filter.prompt_for_data()

        try:
            sorted_member_issues = sorted(team.members, key=lambda s: s.primary_name.user_name)

            while True:
                # Print out a menu of the meta information for each team member
                print_separator(40)
                report_filter.print_description()
                print_separator(40)
                print('[{}]'.format(report_filter.header))
                print(report_filter.column_headers())

                count = 1

                for member_issues in sorted_member_issues:
                    report_filter.clear()
                    # We perform pre-processing and one-off prompting for time duration in .process call
                    report_filter.process_issues(member_issues)
                    print('{:5}: {}'.format(count, report_filter.print_all_counts(member_issues.primary_name.user_name)))
                    count += 1

                print_separator(40)
                cmd = get_input('[#] Integer value to see a detailed breakdown by category. [q] to return to menu:')
                if cmd == 'q':
                    break
                selection = as_int(cmd)
                if selection is None:
                    break

                selection -= 1
                if selection < 0 or selection > len(sorted_member_issues):
                    print('Bad Selection.')
                    continue
                full_member_issues = sorted_member_issues[selection]
                TeamManager._print_member_details(jira_manager, full_member_issues, report_filter)
        except JIRAError as je:
            print('Caught a JIRAError attempting to run a query: {}'.format(je))
            pause()
Exemple #29
0
 def add_view(self) -> None:
     if len(self._jira_connections) == 0:
         if is_yes(
                 'No JiraConnections to add a JiraView to. Would you like to add a connection now?'
         ):
             self.add_connection()
         else:
             return None
     view_name = get_input('Name this view:')
     jira_connection_name = pick_value(
         'Which JIRA Connection does this belong to?',
         list(self._jira_connections.keys()))
     if jira_connection_name is None:
         return
     new_view = JiraView(view_name,
                         self._jira_connections[jira_connection_name])
     self.jira_views[view_name] = new_view
     new_view.edit_view(self, self.team_manager)
     self._save_config()
Exemple #30
0
 def create_jenkins_obj(self, url, username=None, password=None):
     """
     Currently the sole purpose for this method is to have an easy method to
     mock when we don't want to request a real URL.
     :exception ConnectionError: on inability to reach input url
     """
     try:
         return Jenkins(url, username, password)
     except HTTPError as e:
         if e.response.status_code == 401:
             print('401 error for {}. (ctrl+c to hard-quit)'.format(
                 self.name))
             username = get_input('Re-enter username:'******'Re-enter password:'******'username'] = username
             self._auth['password'] = password
             self.create_jenkins_obj(url,
                                     username=username,
                                     password=password)
         else:
             raise e