def generate_topology(level: int, member: Dict[str, Any],
                      topology: Dict[Optional[str], List[Dict[str, Any]]]) -> Iterator[Dict[str, Any]]:
    """Recursively yield members with their names adjusted according to their *level* in the cluster topology.

    .. note::
        The idea is to get a tree view of the members when printing their names. For example, suppose you have a
        cascading replication composed of 3 nodes, say ``postgresql0``, ``postgresql1``, and ``postgresql2``. This
        function would adjust their names to be like this:

        * ``'postgresql0'`` -> ``'postgresql0'``
        * ``'postgresql1'`` -> ``'+ postgresql1'``
        * ``'postgresql2'`` -> ``'  + postgresql2'``

        So, if you ever print their names line by line, you would see something like this:

        .. code-block::

            postgresql0
            + postgresql1
              + postgresql2

    :param level: the current level being inspected in the *topology*.
    :param member: information about the current member being inspected in *level* of *topology*. Should contain at
        least this key:
        * ``name``: name of the node, according to ``name`` configuration;

        But may contain others, which although ignored by this function, will be yielded as part of the resulting
        object. The value of key ``name`` is changed as explained in the note.

    :param topology: each key is the name of a node which has at least one replica attached to it. The corresponding
        value is a list of the attached replicas, each of them with the same structure described for *member*.

    :yields: the current member with its name changed. Besides that reyield values from recursive calls.
    """
    members = topology.get(member['name'], [])

    if level > 0:
        member['name'] = '{0}+ {1}'.format((' ' * (level - 1) * 2), member['name'])

    if member['name']:
        yield member

    for member in members:
        yield from generate_topology(level + 1, member, topology)
Recursively yield members with their names adjusted according to their *level* in the cluster topology.

    .. note::
        The idea is to get a tree view of the members when printing their names. For example, suppose you have a
        cascading replication composed of 3 nodes, say ``postgresql0``, ``postgresql1``, and ``postgresql2``. This
        function would adjust their names to be like this:

        * ``'postgresql0'`` -> ``'postgresql0'``
        * ``'postgresql1'`` -> ``'+ postgresql1'``
        * ``'postgresql2'`` -> ``'  + postgresql2'``

        So, if you ever print their names line by line, you would see something like this:

        .. code-block::

            postgresql0
            + postgresql1
              + postgresql2

    :param level: the current level being inspected in the *topology*.
    :param member: information about the current member being inspected in *level* of *topology*. Should contain at
        least this key:
        * ``name``: name of the node, according to ``name`` configuration;

        But may contain others, which although ignored by this function, will be yielded as part of the resulting
        object. The value of key ``name`` is changed as explained in the note.

    :param topology: each key is the name of a node which has at least one replica attached to it. The corresponding
        value is a list of the attached replicas, each of them with the same structure described for *member*.

    :yields: the current member with its name changed. Besides that reyield values from recursive calls.
    
patroni/ctl.py