1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-26 07:41:33 +03:00
Files
certbot/certbot-apache/certbot_apache/_internal/display_ops.py
Adrien Ferrand 0181a0b07f Fully type certbot apache (#9177)
* Work in progress

* Work in progress

* Work in progress

* Work in progress

* Fix issues around nullability of VirtualHost.path, may discuss that during review

* Work in progress

* Fix remaining types

* Various lint fixes

* Reconfigure tox and mypy to disallow untyped defs globally

* Cleanup compatibility tests

* Use cast for unused v2 logic

* Improve types

* Remove unused comment

* Fix coverage

* Better types

* Fix another type

* Update certbot-apache/certbot_apache/_internal/apacheparser.py

Co-authored-by: alexzorin <alex@zor.io>

* Update certbot-apache/certbot_apache/_internal/assertions.py

Co-authored-by: alexzorin <alex@zor.io>

* Fix type

* Various fixes

* Refactor imports

* Keep naming convention consistent on TypeVars

* Improve types

* Improve types

* Remove remaining Sequence[str] in the project

Co-authored-by: alexzorin <alex@zor.io>
2022-01-31 19:17:40 +11:00

135 lines
4.5 KiB
Python

"""Contains UI methods for Apache operations."""
import logging
from typing import Iterable
from typing import List
from typing import Optional
from typing import Sequence
from typing import Tuple
from certbot_apache._internal.obj import VirtualHost
from certbot import errors
from certbot.compat import os
from certbot.display import util as display_util
logger = logging.getLogger(__name__)
def select_vhost_multiple(vhosts: Optional[List[VirtualHost]]) -> List[VirtualHost]:
"""Select multiple Vhosts to install the certificate for
:param vhosts: Available Apache VirtualHosts
:type vhosts: :class:`list` of type `~VirtualHost`
:returns: List of VirtualHosts
:rtype: :class:`list`of type `~VirtualHost`
"""
if not vhosts:
return []
tags_list = [vhost.display_repr()+"\n" for vhost in vhosts]
# Remove the extra newline from the last entry
if tags_list:
tags_list[-1] = tags_list[-1][:-1]
code, names = display_util.checklist(
"Which VirtualHosts would you like to install the wildcard certificate for?",
tags=tags_list, force_interactive=True)
if code == display_util.OK:
return_vhosts = _reversemap_vhosts(names, vhosts)
return return_vhosts
return []
def _reversemap_vhosts(names: Iterable[str], vhosts: Iterable[VirtualHost]) -> List[VirtualHost]:
"""Helper function for select_vhost_multiple for mapping string
representations back to actual vhost objects"""
return_vhosts = []
for selection in names:
for vhost in vhosts:
if vhost.display_repr().strip() == selection.strip():
return_vhosts.append(vhost)
return return_vhosts
def select_vhost(domain: str, vhosts: Sequence[VirtualHost]) -> Optional[VirtualHost]:
"""Select an appropriate Apache Vhost.
:param str domain: Domain for vhost selection
:param vhosts: Available Apache VirtualHosts
:type vhosts: :class:`list` of type `~VirtualHost`
:returns: VirtualHost or `None`
:rtype: `~obj.Vhost` or `None`
"""
if not vhosts:
return None
code, tag = _vhost_menu(domain, vhosts)
if code == display_util.OK:
return vhosts[tag]
return None
def _vhost_menu(domain: str, vhosts: Iterable[VirtualHost]) -> Tuple[str, int]:
"""Select an appropriate Apache Vhost.
:param vhosts: Available Apache Virtual Hosts
:type vhosts: :class:`list` of type `~obj.Vhost`
:returns: Display tuple - ('code', tag')
:rtype: `tuple`
"""
# Free characters in the line of display text (9 is for ' | ' formatting)
free_chars = display_util.WIDTH - len("HTTPS") - len("Enabled") - 9
if free_chars < 2:
logger.debug("Display size is too small for "
"certbot_apache._internal.display_ops._vhost_menu()")
# This runs the edge off the screen, but it doesn't cause an "error"
filename_size = 1
disp_name_size = 1
else:
# Filename is a bit more important and probably longer with 000-*
filename_size = int(free_chars * .6)
disp_name_size = free_chars - filename_size
choices = []
for vhost in vhosts:
if len(vhost.get_names()) == 1:
disp_name = next(iter(vhost.get_names()))
elif not vhost.get_names():
disp_name = ""
else:
disp_name = "Multiple Names"
choices.append(
"{fn:{fn_size}s} | {name:{name_size}s} | {https:5s} | "
"{active:7s}".format(
fn=os.path.basename(vhost.filep)[:filename_size],
name=disp_name[:disp_name_size],
https="HTTPS" if vhost.ssl else "",
active="Enabled" if vhost.enabled else "",
fn_size=filename_size,
name_size=disp_name_size),
)
try:
code, tag = display_util.menu(
f"We were unable to find a vhost with a ServerName "
f"or Address of {domain}.{os.linesep}Which virtual host would you "
f"like to choose?",
choices, force_interactive=True)
except errors.MissingCommandlineFlag:
msg = (
f"Encountered vhost ambiguity when trying to find a vhost for "
f"{domain} but was unable to ask for user "
f"guidance in non-interactive mode. Certbot may need "
f"vhosts to be explicitly labelled with ServerName or "
f"ServerAlias directives.")
logger.error(msg)
raise errors.MissingCommandlineFlag(msg)
return code, tag