Exemplo n.º 1
0
    def _onlynew(self, msg, id=None, misc=''):
        """
        log an only-new mode message

        Accepts a message to be printed out when running in "only-new" mode. A
        message may be accompanied by an identifier which should be translated
        to a name (if possible).

        Args:
            msg: the message
            id (optional): identifier (name mapping) associated with the message
        """
        s = '[only-new] '
        s += msg
        if id and id in self._name_cache:
            s += ' ' + self._name_cache[id]
        if id:
            s += ' ({})'.format(id)
        ConfluenceLogger.info(s + min(80, 80 - len(s)) * ' ') # 80c-min clearing
Exemplo n.º 2
0
    def _dryrun(self, msg, id_=None, misc=''):
        """
        log a dry run mode message

        Accepts a message to be printed out when running in "dry run" mode. A
        message may be accompanied by an identifier which should be translated
        to a name (if possible).

        Args:
            msg: the message
            id_ (optional): identifier (name mapping) associated with the message
            misc (optional): additional information to append
        """
        s = '[dryrun] '
        s += msg
        if id_ and id_ in self._name_cache:
            s += ' ' + self._name_cache[id_]
        if id_:
            s += ' ({})'.format(id_)
        if misc:
            s += ' ' + misc
        logger.info(s + min(80, 80 - len(s)) * ' ')  # 80c-min clearing
Exemplo n.º 3
0
def _inline_all_toctrees(builder, docnameset, docname, tree, colorfunc,
                         traversed, replace):
    tree = cast(nodes.document, tree.deepcopy())
    for toctreenode in list(tree.traverse(addnodes.toctree)):
        newnodes = []
        includefiles = map(str, toctreenode['includefiles'])
        for includefile in includefiles:
            if includefile not in traversed:
                try:
                    traversed.append(includefile)
                    logger.info(colorfunc(includefile) + " ", nonl=True)
                    subtree = _inline_all_toctrees(
                        builder, docnameset, includefile,
                        builder.env.get_doctree(includefile), colorfunc,
                        traversed, replace)
                    docnameset.add(includefile)
                except Exception:
                    logger.warn(
                        __('toctree contains ref to nonexisting file %r'),
                        includefile,
                        location=docname)
                else:
                    sof = addnodes.start_of_file(docname=includefile)
                    sof.children = subtree.children
                    for sectionnode in sof.traverse(nodes.section):
                        if 'docname' not in sectionnode:
                            sectionnode['docname'] = includefile
                    newnodes.append(sof)

        if replace:
            toctreenode.parent.replace(toctreenode, newnodes)
        else:
            for node in newnodes:
                toctreenode.parent.append(node)

    return tree
Exemplo n.º 4
0
    def connect(self):
        self.rest_client = Rest(self.config)
        server_url = self.config.confluence_server_url

        try:
            rsp = self.rest_client.get('space', {
                'spaceKey': self.space_key,
                'limit': 1
            })
        except ConfluenceBadApiError as e:
            raise ConfluenceBadServerUrlError(server_url, e)

        # if no size entry is provided, this a non-Confluence API server
        if 'size' not in rsp:
            raise ConfluenceBadServerUrlError(
                server_url,
                'server did not provide an expected response (no size)')

        # handle if the provided space key was not found
        if rsp['size'] == 0:
            if self.debug:
                logger.info('''could not find the configured space

(notice to debugging user)
Either the space does not exist, or the user does not have permission to see
the space. Another space search will be performed to sanity check the
configuration to see if a similar space key exists, which can hint to a user
that the space key may be misconfigured. If the following search request
results in an access restriction, it is most likely that the authentication
options are not properly configured, even if the previous search request
reported a success (which can be permitted for anonymous users).
''')

            extra_desc = ''

            # If the space key was not found, attempt to search for the space
            # based off its descriptive name. If something is found, hint to the
            # user to use a space's key value instead.
            search_fields = {
                'cql': 'type=space and space.title~"' + self.space_key + '"',
                'limit': 2,
            }
            rsp = self.rest_client.get('search', search_fields)

            if rsp['size'] == 1:
                detected_space = rsp['results'][0]
                space_key = detected_space['space']['key']
                space_name = detected_space['title']
                extra_desc = \
                    '''\n\n''' \
                    '''There appears to be a space '{0}' which has a name ''' \
                    ''''{1}'. Did you mean to use this space?\n''' \
                    '''\n''' \
                    '''   confluence_space_key = '{0}'\n''' \
                    ''''''.format(space_key, space_name)

            elif rsp['size'] > 1:
                extra_desc = \
                    '''\n\n''' \
                    '''Multiple spaces have been detected which use the ''' \
                    '''name '{}'. The unique key of the space should be ''' \
                    '''used instead. See also:\n\n''' \
                    '''   https://support.atlassian.com/confluence-cloud/docs/choose-a-space-key/\n''' \
                    ''''''.format(self.space_key)

            pw_set = bool(self.config.confluence_server_pass)
            token_set = bool(self.config.confluence_publish_token)

            raise ConfluenceBadSpaceError(self.space_key,
                                          self.config.confluence_server_user,
                                          pw_set, token_set, extra_desc)

        # sanity check that we have any result
        if 'results' not in rsp or not rsp['results']:
            raise ConfluenceBadServerUrlError(
                server_url,
                'server did not provide an expected response (no results)')

        result = rsp['results'][0]

        if not isinstance(result, dict) or not result.get('name'):
            raise ConfluenceBadServerUrlError(
                server_url,
                'server did not provide an expected response (no name)')

        # track required space information
        self.space_display_name = result['name']
        self.space_type = result['type']
Exemplo n.º 5
0
 def __exit__(self, type, value, traceback):
     if type:
         ConfluenceLogger.info(__('failed'))
     else:
         ConfluenceLogger.info(__('done'))
Exemplo n.º 6
0
 def __enter__(self):
     ConfluenceLogger.info(bold(self.msg + '... '), nonl=True)
Exemplo n.º 7
0
def wipe_main(args_parser):
    """
    wipe mainline

    The mainline for the 'wipe' action.

    Args:
        args_parser: the argument parser to use for argument processing

    Returns:
        the exit code
    """

    args_parser.add_argument('--danger', action='store_true')

    known_args = sys.argv[1:]
    args, unknown_args = args_parser.parse_known_args(known_args)
    if unknown_args:
        logger.warn('unknown arguments: {}'.format(' '.join(unknown_args)))

    work_dir = args.work_dir if args.work_dir else os.getcwd()

    # protection warning
    if not args.danger:
        print('')
        sys.stdout.flush()
        logger.warn('!!! DANGER DANGER DANGER !!!')
        print("""
A request has been made to attempt to wipe the pages from a configured
Confluence instance. This is a helper utility call to assist a user in cleaning
out a space since removing a bulk set of data may not be trivial for a user.

Note that this action is not reversible with this tool and may require
assistance from an administrator from a Confluence instance to recover pages.
Only use this action if you know what you are doing.

To use this action, the argument '--danger' must be set.
            """)
        sys.stdout.flush()
        logger.warn('!!! DANGER DANGER DANGER !!!')
        print('')
        return 1

    # check configuration and prepare publisher
    publisher = None
    with TemporaryDirectory() as tmp_dir:
        with docutils_namespace():
            app = Sphinx(
                work_dir,  # document sources
                work_dir,  # directory with configuration
                tmp_dir,  # output for generated documents
                tmp_dir,  # output for doctree files
                'confluence')  # builder to execute

            aggressive_search = app.config.confluence_adv_aggressive_search
            server_url = app.config.confluence_server_url
            space_name = app.config.confluence_space_name

            # initialize the publisher (if permitted)
            if app.config.confluence_publish:
                process_ask_configs(app.config)

                publisher = ConfluencePublisher()
                publisher.init(app.config)

    if not publisher:
        print('(error) publishing not configured in sphinx configuration')
        return 1

    # reminder warning
    print('')
    sys.stdout.flush()
    logger.warn('!!! DANGER DANGER DANGER !!!')
    print("""
A request has been made to attempt to wipe the pages from a configured
Confluence instance.  This action is not reversible with this tool and may
require assistance from an administrator from a Confluence instance to recover
pages. Only use this action if you know what you are doing.
        """)
    sys.stdout.flush()

    logger.warn('!!! DANGER DANGER DANGER !!!')
    print('')

    if not ask_question('Are you sure you want to continue?'):
        return 0
    print('')

    # user has confirmed; start an attempt to wipe
    publisher.connect()

    if aggressive_search:
        legacy_pages = publisher.getDescendantsCompat(None)
    else:
        legacy_pages = publisher.getDescendants(None)
    if not legacy_pages:
        print('No pages are published on this space. Exiting...')
        return 0

    print('         URL:', server_url)
    print('       Space:', space_name)
    logger.note('       Pages: All Pages')
    print(' Total pages:', len(legacy_pages))
    print('')
    if not ask_question('Are you sure you want to REMOVE these pages?'):
        return 0
    print('')

    logger.info('Removing pages...', nonl=True)
    for page_id in legacy_pages:
        publisher.removePage(page_id)
        logger.info('.', nonl=True)
    logger.info(' done\n')

    return 0
Exemplo n.º 8
0
 def __exit__(self, type_, value, traceback):
     if type_:
         logger.info(__('failed'))
     else:
         logger.info(__('done'))
Exemplo n.º 9
0
 def __enter__(self):
     logger.info(bold(self.msg + '... '), nonl=True)
Exemplo n.º 10
0
def wipe_main(args_parser):
    """
    wipe mainline

    The mainline for the 'wipe' action.

    Args:
        args_parser: the argument parser to use for argument processing

    Returns:
        the exit code
    """

    args_parser.add_argument('--danger', action='store_true')
    args_parser.add_argument('--parent', '-P', action='store_true')

    known_args = sys.argv[1:]
    args, unknown_args = args_parser.parse_known_args(known_args)
    if unknown_args:
        logger.warn('unknown arguments: {}'.format(' '.join(unknown_args)))

    work_dir = args.work_dir if args.work_dir else os.getcwd()

    # protection warning
    if not args.danger:
        print('')
        sys.stdout.flush()
        logger.warn('!!! DANGER DANGER DANGER !!!')
        print("""
A request has been made to attempt to wipe the pages from a configured
Confluence instance. This is a helper utility call to assist a user in cleaning
out a space since removing a bulk set of data may not be trivial for a user.

Note that this action is not reversible with this tool and may require
assistance from an administrator from a Confluence instance to recover pages.
Only use this action if you know what you are doing.

To use this action, the argument '--danger' must be set.
            """)
        sys.stdout.flush()
        logger.warn('!!! DANGER DANGER DANGER !!!')
        return 1

    # check configuration and prepare publisher
    dryrun = False
    publisher = None

    try:
        with temp_dir() as tmp_dir:
            with docutils_namespace():
                app = Sphinx(
                    work_dir,  # document sources
                    work_dir,  # directory with configuration
                    tmp_dir,  # output for built documents
                    tmp_dir,  # output for doctree files
                    'confluence',  # builder to execute
                    status=sys.stdout,  # sphinx status output
                    warning=sys.stderr)  # sphinx warning output

                aggressive_search = app.config.confluence_adv_aggressive_search
                dryrun = app.config.confluence_publish_dryrun
                server_url = app.config.confluence_server_url
                space_key = app.config.confluence_space_key
                parent_ref = app.config.confluence_parent_page

                # initialize the publisher (if permitted)
                if app.config.confluence_publish:
                    process_ask_configs(app.config)

                    publisher = ConfluencePublisher()
                    publisher.init(app.config)

    except Exception:
        sys.stdout.flush()
        logger.error(traceback.format_exc())
        if os.path.isfile(os.path.join(work_dir, 'conf.py')):
            logger.error('unable to load configuration')
        else:
            logger.error('no documentation/missing configuration')
        return 1

    if not publisher:
        logger.error('publishing not configured in sphinx configuration')
        return 1

    if args.parent and not parent_ref:
        logger.error('parent option provided but no parent page is configured')
        return 1

    # reminder warning
    print('')
    sys.stdout.flush()
    logger.warn('!!! DANGER DANGER DANGER !!!')
    print("""
A request has been made to attempt to wipe the pages from a configured
Confluence instance. This action is not reversible with this tool and may
require assistance from an administrator from a Confluence instance to recover
pages. Only use this action if you know what you are doing.
        """)
    sys.stdout.flush()

    logger.warn('!!! DANGER DANGER DANGER !!!')
    print('')

    if not ask_question('Are you sure you want to continue?'):
        return 0
    print('')

    # user has confirmed; start an attempt to wipe
    publisher.connect()

    base_page_id = None
    if args.parent:
        base_page_id = publisher.get_base_page_id()

    if aggressive_search:
        legacy_pages = publisher.get_descendants_compat(base_page_id)
    else:
        legacy_pages = publisher.get_descendants(base_page_id)

    print('         URL:', server_url)
    print('       Space:', space_key)
    if base_page_id:
        logger.note('       Pages: Child pages of ' + parent_ref)
    else:
        logger.note('       Pages: All Pages')
    print(' Total pages:', len(legacy_pages))
    if dryrun:
        print('     Dry run:', 'Enabled (no pages will be removed)')

    if not legacy_pages:
        print('')
        print('No pages detected on this space. Exiting...')
        return 0

    if args.verbose:
        print('-------------------------')
        page_names = []
        for p in legacy_pages:
            page_names.append(publisher._name_cache[p])
        sorted(page_names)
        print('\n'.join(page_names))
        print('-------------------------')

    print('')
    if not ask_question('Are you sure you want to REMOVE these pages?'):
        return 0
    print('')

    logger.info('Removing pages...', nonl=True)
    if dryrun:
        logger.info('')
    for page_id in legacy_pages:
        publisher.remove_page(page_id)
        if not dryrun:
            logger.info('.', nonl=True)
    if not dryrun:
        logger.info(__('done'))

    return 0