Exemplo n.º 1
0
    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()
Exemplo n.º 2
0
    def remove_view(self):
        if len(self.jira_views) == 0:
            print('No views to remove.')
            return
        to_remove = pick_value('Select a view to delete or [q]uit: ',
                               list(self.jira_views.keys()))
        if to_remove is None:
            return

        # Build list of Dashboards this is going to invalidate to confirm
        affected_dashes = []
        for dash in list(self.jira_dashboards.values()):
            if dash.contains_jira_view(to_remove):
                print(
                    'WARNING: Removing this view will also remove JiraDashboard: {}.'
                    .format(dash))
                affected_dashes.append(dash.name)

        if is_yes('Are you sure you want to delete {}?'.format(to_remove)):
            self.jira_views[to_remove].delete_config()
            del self.jira_views[to_remove]

            # Determine if any dashboards exist w/this view and delete them
            for dash_name in affected_dashes:
                del self.jira_dashboards[dash_name]

            self._save_config()
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
 def view_cached_jobs(self):
     if self.active_connection.job_names:
         view_options = sorted(self.active_connection.view_names)
         all_jobs = '* All Jobs'
         view_options.append(all_jobs)
         view_name = pick_value('Which jobs would you like to view?',
                                view_options)
         if view_name:
             if view_name == all_jobs:
                 self.print_job_options(self.active_connection.jobs,
                                        connection=True)
             else:
                 jobs_to_print = []
                 job_names = self.active_connection.jenkins_views[
                     view_name].job_names
                 if job_names:
                     for job_name in job_names:
                         jobs_to_print.append(
                             self.active_connection.jenkins_jobs[job_name])
                     self.print_job_options(jobs_to_print, connection=True)
                 else:
                     print('No jobs to print in this view.')
     else:
         if is_yes(
                 'There are no cached jobs for the current connection. Would you like to download jobs now?'
         ):
             self.download_jobs()
Exemplo n.º 5
0
    def add_view(self):
        view_name = pick_value('Which Jenkins view would you like to save?',
                               self.active_connection.get_list_of_views())
        if view_name:
            if view_name == 'Dev':
                dev_view_name = pick_value(
                    'Which Jenkins dev view would you like to save?',
                    self.active_connection.get_list_of_views(view_name))
                if dev_view_name:
                    dev_view_name = 'Dev-{}'.format(dev_view_name)
                    self.active_connection.jenkins_views[
                        dev_view_name] = self.active_connection.get_view(
                            dev_view_name)
                    self.active_connection.save_connection_config()
                    view_name = dev_view_name
            else:
                self.active_connection.jenkins_views[
                    view_name] = self.active_connection.get_view(view_name)
                self.active_connection.save_connection_config()
            print('Successfully added view: {}'.format(view_name))
            pause()

            if is_yes('Would you like to download jobs for this view now?'):
                self.active_connection.download_jobs(view_name)
                self.active_connection.save_job_data()
                print('Successfully downloaded jobs for view: {}'.format(
                    view_name))
                pause()
Exemplo n.º 6
0
    def add_custom_report_job(self):
        if self.connection_names:
            connection_name = pick_value(
                'Which Jenkins Connection would you like to add jobs from?',
                self.connection_names)
            if connection_name:
                connection = self.jenkins_connections[connection_name]
                if connection_name in self.active_report.connection_names:
                    job_options = [
                        job_name for job_name in connection.job_names
                        if job_name not in
                        self.active_report.connection_dict[connection_name]
                    ]
                else:
                    job_options = connection.job_names

                while True:
                    job_name = pick_value(
                        'Which Jenkins job would you like to add?',
                        job_options)
                    if job_name:
                        self.active_report.add_job_to_report(
                            job_name, connection_name)
                        self.active_report.save_report_config()
                        print('Successfully added job: {}'.format(job_name))
                        job_options.remove(job_name)
                    else:
                        break
        else:
            if is_yes(
                    'No Jenkins connections to add jobs from. Would you like to add one now?'
            ):
                self.active_connection = self.add_connection()
                self._main_menu.go_to_jenkins_connection_menu()
Exemplo n.º 7
0
 def view_custom_report(self):
     if self.active_report.job_names:
         job_list = self.active_report.get_job_list(self)
         self.print_job_options(job_list)
     else:
         if is_yes(
                 'Attempted to run report with no jobs. Would you like to add jobs now?'
         ):
             self.add_custom_report_job()
Exemplo n.º 8
0
 def _prompt_connection_add_if_none(self) -> bool:
     """
     :return: True if either a new connection is added or connections already exist
     """
     if len(self._jira_connections) == 0:
         if is_yes(
                 'Did not find any JiraConnections to cache a JiraProject. Would you like to add one now?'
         ):
             self.add_connection()
             return True
         else:
             return False
     return True
Exemplo n.º 9
0
 def select_active_report(self):
     if self.jenkins_reports:
         report_name = pick_value(
             'Which custom report would you like to open?',
             self.report_names)
         if report_name:
             self.active_report = self.get_custom_report(report_name)
             self._main_menu.go_to_jenkins_report_menu()
     else:
         if is_yes('No custom reports. Would you like to add one now?'):
             self.add_custom_report()
             self.active_report = self.get_custom_report(
                 self.report_names[0])
             self._main_menu.go_to_jenkins_report_menu()
Exemplo n.º 10
0
 def remove_team(self) -> Optional[str]:
     """
     :return: Name of team that was removed, None if none.
     """
     if len(self._teams) == 0:
         print('No teams currently defined.')
         return None
     to_remove = pick_value('Remove which team?', list(self._teams.keys()), True, 'Cancel')
     if to_remove is None:
         return None
     if is_yes('Are you sure you want to delete {}?'.format(to_remove)):
         del self._teams[to_remove]
         self._save_config()
         return to_remove
     return None
Exemplo n.º 11
0
 def select_active_connection(self):
     if self.jenkins_connections:
         connection_name = pick_value(
             'Which Jenkins connection would you like to open?',
             self.connection_names)
         if connection_name:
             self.active_connection = self.get_connection(connection_name)
             self._main_menu.go_to_jenkins_connection_menu()
     else:
         if is_yes(
                 'No Jenkins connections. Would you like to add one now?'):
             self.add_connection()
             self.active_connection = self.get_connection(
                 self.connection_names[0])
             self._main_menu.go_to_jenkins_connection_menu()
Exemplo n.º 12
0
 def remove_connection(self):
     """
     Removes an existing url/user/pass JIRA connection and the corresponding Jira object
     """
     selection = pick_value('Remove which jira connection? ',
                            list(self._jira_connections.keys()), True,
                            'Cancel')
     if selection is None:
         return
     print(
         'About to delete: {}, all related views, and all offline cached JiraProject data.'
         .format(selection))
     if is_yes('Are you sure?'):
         jira_connection = self._jira_connections[selection]
         jira_connection.delete_owned_views(self)
         jira_connection.delete_cached_project_data()
         del self._jira_connections[selection]
         self._save_config()
Exemplo n.º 13
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()
Exemplo n.º 14
0
    def create_new_member_alias(self, jira_manager):
        # type: (JiraManager) -> None
        """
        This linkage is performed on the logical 'Team' level rather than per JiraConnection.
        """
        if len(self._teams) == 0:
            print('Must first add a team before adding a linked member.')
            return

        count = 0
        for team in list(self._teams.values()):
            count += len(team.members)
        if count == 0:
            print(
                'No members found on any teams. Add members before attempting to link members.'
            )
            return

        # The linkage allows addition of >= 1 linked JiraUserName to whatever root member we want to add to.
        target_member = self._pick_member_for_linkage_operation('Add')

        changed = False
        while True:
            print('Current state of user: {}'.format(target_member))
            jira_connection_to_alias = jira_manager.pick_jira_connection(
                'Alias to a user account on which JIRA connection?')
            if jira_connection_to_alias is None:
                break

            # We have our target jira username at this point.
            user_to_alias_to = jira_connection_to_alias.pick_single_assignee()
            if user_to_alias_to is None:
                break

            new_user_alias = JiraUserName(
                user_to_alias_to, jira_connection_to_alias.connection_name,
                'alias')
            target_member.add_alias(new_user_alias)
            changed = True

            if not is_yes('Add another alias?'):
                break
        if changed:
            self._save_config()
Exemplo n.º 15
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
Exemplo n.º 16
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()
Exemplo n.º 17
0
 def remove_connection(self):
     if self.jenkins_connections:
         connection_name = pick_value(
             'Which Jenkins connection would you like to remove?',
             self.connection_names)
         if connection_name:
             print('About to remove: {}'.format(connection_name))
             if is_yes('Are you sure?'):
                 self.jenkins_connections.pop(connection_name)
                 self.save_jenkins_config()
                 print('Successfully removed connection: {}'.format(
                     connection_name))
                 pause()
             else:
                 print('Remove aborted.')
                 pause()
     else:
         print('No Jenkins connections to remove.')
         pause()
Exemplo n.º 18
0
    def delete_cached_jira_project(self):
        jira_connection_name = pick_value(
            'Delete cached project data for which JiraConnection?',
            [x.connection_name for x in self.jira_connections()])
        if jira_connection_name is None:
            return

        jira_connection = self._jira_connections[jira_connection_name]
        project_cache_to_delete = pick_value(
            'Delete cached data for which JiraProject?',
            jira_connection.cached_project_names)
        if project_cache_to_delete is None:
            return

        if is_yes('About to delete locally cached content: {}. Are you sure?'.
                  format(
                      jira_connection.maybe_get_cached_jira_project(
                          project_cache_to_delete))):
            jira_connection.delete_cached_jira_project(project_cache_to_delete)
Exemplo n.º 19
0
    def build(cls, jira_views: Dict[str,
                                    JiraView]) -> Optional['JiraDashboard']:
        """
        Links 2 or more JiraViews together, combining their results for display
        """
        if len(jira_views) <= 1:
            print(
                'Need at least 2 JiraViews to create a dashboard. Please create more JiraViews first.'
            )
            return None

        view_name_options = list(jira_views.keys())
        dash_name = get_input('Name this dashboard:', lowered=False)
        view_name = pick_value('Include which view?', view_name_options, True,
                               'Cancel')
        if view_name is None:
            return None

        dash_views = {view_name: jira_views[view_name]}
        view_name_options.remove(view_name)

        view_name = pick_value('Second view?', view_name_options, False)
        # make mypy happy - doesn't realize False means we can't have None
        if view_name is None:
            return None
        dash_views[view_name] = jira_views[view_name]
        view_name_options.remove(view_name)

        while len(view_name_options) > 0:
            if is_yes('Add another?'):
                view_name = pick_value('What view?', view_name_options, True,
                                       '[q] Cancel')
                if view_name == 'q' or view_name is None:
                    break
                dash_views[view_name] = jira_views[view_name]
                view_name_options.remove(view_name)
            else:
                break

        return JiraDashboard(dash_name, dash_views)
Exemplo n.º 20
0
    def remove_view(self):
        if self.active_connection.jenkins_views:
            view_name = pick_value(
                'Which Jenkins view would you like to remove?',
                self.active_connection.view_names)

            if view_name:
                print('About to delete: {}'.format(view_name))
                if is_yes('Are you sure?'):
                    del self.active_connection.jenkins_views[view_name]
                    self.active_connection.save_connection_config()
                    file_name = os.path.join(jenkins_views_dir,
                                             "{}.cfg".format(view_name))
                    if os.path.exists(file_name):
                        os.remove(file_name)
                        print('{} view deleted.'.format(view_name))
                    else:
                        print('Attempted to remove view {}'.format(view_name))
                        print('View path {} does not exist'.format(file_name))
                else:
                    print('Remove aborted.')
                pause()
        else:
            print('No Jenkins views to remove.')
Exemplo n.º 21
0
    def report_fix_version(self) -> None:
        """
        Creates a report of all tickets, including dependencies, to the input FixVersion.
        """

        # Only support creating of this on a single JiraConnection, with the assumption that multiple projects on that
        # connection can share a FixVersion, but these won't straddle to exterior Jira instances
        target_connection = self.pick_jira_connection(
            'FixVersion report for which JiraConnection?')
        if target_connection is None:
            return

        open_only = is_yes('Show only unresolved issues?')

        to_match = get_input('Input substring to search fixversions for:',
                             False)
        available_versions = set()
        for jira_project in target_connection.cached_projects:
            for jira_issue in jira_project.jira_issues.values():
                for fix in jira_issue['fixVersions'].split(','):
                    if to_match in fix:
                        available_versions.add(fix)

        report_version = pick_value('Generate report for which FixVersion?',
                                    list(available_versions))
        if report_version is None:
            return

        print('Generating report on: {}'.format(report_version))

        # Now find all "primary root" members on this FixVersion, generate a list of matching, then display w/dependency
        # chains enabled
        matching_issues = set()
        for jira_project in target_connection.cached_projects:
            for jira_issue in jira_project.jira_issues.values():
                if jira_issue.has_fix_version(report_version):
                    if (open_only and jira_issue.is_open) or not open_only:
                        matching_issues.add(jira_issue)

        df = DisplayFilter.default()
        df.open_only = open_only
        df.include_column('fixVersions', 'FixVersion', 10, 2)

        # sort our keys by issuekey
        sorted_results = JiraUtils.sort_custom_jiraissues_by_key(
            list(matching_issues))
        del matching_issues

        issues = df.display_and_return_sorted_issues(self, sorted_results, 1,
                                                     None, True)
        while True:
            choice = get_input(
                '[#] to open an issue in browser, [p] to print report again, [q] to quit report: '
            )
            if choice == 'q':
                break
            elif choice == 'p':
                df.display_and_return_sorted_issues(self, sorted_results, 1,
                                                    None, True)
            try:
                int_choice = int(choice) - 1
                if int_choice < 0 or int_choice > len(issues) - 1:
                    raise ValueError('oops')
                chosen_issue = issues[int_choice]
                if not chosen_issue.is_cached:
                    print(
                        'Cannot open browser for non-cached issue (don\'t know url). Cache offline to inspect {}.'
                        .format(chosen_issue.issue_key))
                else:
                    jira_conn = self._jira_connections[
                        chosen_issue.jira_connection_name]
                    JiraUtils.open_issue_in_browser(jira_conn.url,
                                                    chosen_issue.issue_key)
            except ValueError:
                print('Bad input. Try again.')
Exemplo n.º 22
0
    def __init__(self, team_manager):
        """
        Recreates any JiraConnections and JiraViews based on saved data in conf/jira.cfg
        """
        # Holds connected Jira objects to be queried by JiraViews
        self._jira_connections = {}  # type: Dict[str, JiraConnection]

        # JiraViews, caching filters for different ways to view Jira Data. Implicit 1:1 JiraConnection to JiraView
        self.jira_views = {}  # type: Dict[str, JiraView]

        self.jira_dashboards = {}  # type: Dict[str, JiraDashboard]

        # Used during JiraDependency resolution to notify user of missing JiraProjects
        self.missing_project_counts = {}  # type: Dict[str, int]

        self._display_filter = DisplayFilter.default()

        if os.path.exists(jira_conf_file):
            config_parser = configparser.RawConfigParser()
            config_parser.read(jira_conf_file)

            connection_names = []
            if config_parser.has_section(
                    'JiraManager') and config_parser.has_option(
                        'JiraManager', 'Connections'):
                connection_names = config_parser.get('JiraManager',
                                                     'Connections').split(',')

            # JiraConnections are the root of our container hierarchy
            for connection_name in connection_names:
                if connection_name == '':
                    pass
                try:
                    jira_connection = JiraConnection.from_file(connection_name)
                    # If we had an error on init we obviously cannot add this
                    if jira_connection is None:
                        continue
                    self._jira_connections[
                        jira_connection.connection_name] = jira_connection
                except ConfigError as ce:
                    print('ConfigError with project {}: {}'.format(
                        connection_name, ce))

            # Construct JiraViews so they can be used during JiraDashboard creation.
            view_names = []
            if config_parser.has_option('JiraManager', 'Views'):
                view_names = config_parser.get('JiraManager',
                                               'Views').split(',')

            for name in view_names:
                try:
                    jv = JiraView.from_file(self, name, team_manager)
                    self.jira_views[jv.name] = jv
                except ConfigError as ce:
                    print('ConfigError with jira view {}: {}'.format(name, ce))

            if config_parser.has_section('Dashboards'):
                for dash in config_parser.options('Dashboards'):
                    dash_views = {}
                    for view in view_names:
                        if view not in self.jira_views:
                            print(
                                'Found dashboard {} with invalid view: {}. Skipping init: manually remove from config.'
                                .format(dash, view))
                            break
                        dash_views[view] = self.jira_views[view]
                    self.jira_dashboards[dash] = JiraDashboard(
                        dash, dash_views)

        if len(self._jira_connections) == 0:
            print_separator(30)
            print(
                'No JIRA Connections found. Prompting to add first connection.'
            )
            self.add_connection()

        # Initialize JiraProjects from locally cached files
        for file_name in os.listdir(jira_project_dir):
            full_path = os.path.join(jira_project_dir, file_name)
            print(
                'Processing locally cached JiraProject: {}'.format(full_path))
            # Init based on matching the name of this connection and .cfg
            print_separator(30)
            try:
                new_jira_project = JiraProject.from_file(full_path, self)
                if new_jira_project is None:
                    print('Error initializing from {}. Skipping'.format(
                        full_path))
                    break
                if new_jira_project.jira_connection is None:
                    add = get_input(
                        'Did not find JiraConnection for JiraProject: {}. Would you like to add one now? (y/n)'
                    )
                    if add == 'y':
                        new_jira_connection = self.add_connection(
                            'Name the connection (reference url: {}):'.format(
                                new_jira_project.url))
                        new_jira_connection.save_config()
                        new_jira_project.jira_connection = new_jira_connection
                    else:
                        print(
                            'Did not add JiraConnection, so cannot link and use JiraProject.'
                        )
                        continue
                print('Updating with new data from JIRA instance')
                new_jira_project.refresh()
                new_jira_project.jira_connection.add_and_link_jira_project(
                    new_jira_project)
            except (configparser.NoSectionError, ConfigError) as e:
                print(
                    'WARNING! Encountered error initializing JiraProject from file {}: {}'
                    .format(full_path, e))
                print(
                    'This JiraProject will not be initialized. Remove it manually from disk in conf/jira/projects and data/jira/'
                )

        if os.path.exists('conf/custom_params.cfg'):
            config_parser = configparser.RawConfigParser()
            config_parser.read('conf/custom_params.cfg')
            custom_projects = config_parser.get('CUSTOM_PROJECTS',
                                                'project_names').split(',')

            for project_name in custom_projects:
                argus_debug(
                    'Processing immutable config for custom project: {}'.
                    format(project_name))
                # Find the JiraConnection w/matching URL, if any
                url = config_parser.get(project_name, 'url').rstrip('/')

                jira_project = self.maybe_get_cached_jira_project(
                    url, project_name)
                if jira_project is not None:
                    # Don't need to cache since already done on ctor for JiraProject
                    argus_debug('Project already initialized. Skipping.')
                    continue

                # Didn't find the JiraProject, so we need to build one, cache, and link.
                custom_fields = {}
                field_names = config_parser.get(project_name,
                                                'custom_fields').split(',')
                for field in field_names:
                    custom_fields[field] = config_parser.get(
                        project_name, field)

                parent_jira_connection = None
                for jira_connection in list(self._jira_connections.values()):
                    if jira_connection.url == url:
                        parent_jira_connection = jira_connection
                        break

                # Create a JiraConnection for this JiraProject if we do not yet have one
                if parent_jira_connection is None:
                    print(
                        'WARNING! Did not find JiraConnection for project: {}, attempting to match url: {}'
                        .format(project_name, url))
                    print('Known JiraConnections and their urls:')
                    for jira_connection in list(
                            self._jira_connections.values()):
                        print('   {}: {}'.format(
                            jira_connection.connection_name,
                            jira_connection.url))
                    if is_yes('Would you like to add one now?'):
                        parent_jira_connection = self.add_connection(
                            'Name the connection (reference url: {}):'.format(
                                url))
                    else:
                        print(
                            'JiraProject data and config will not be added nor cached. Either add it manually or restart Argus and reply y'
                        )
                        break

                new_jira_project = JiraProject(parent_jira_connection,
                                               project_name, url,
                                               custom_fields)
                new_jira_project.refresh()
                parent_jira_connection.add_and_link_jira_project(
                    new_jira_project)
        print('Resolving dependencies between JiraIssues')
        self._resolve_issue_dependencies()
        print('JiraManager initialization complete.')