display_ops.py
 1  """Contains UI methods for Apache operations."""
 2  import logging
 3  import os
 4  
 5  import zope.component
 6  
 7  from letsencrypt import interfaces
 8  
 9  import letsencrypt.display.util as display_util
10  
11  
12  logger = logging.getLogger(__name__)
13  
14  
15  def select_vhost(domain, vhosts):
16      """Select an appropriate Apache Vhost.
17  
18      :param vhosts: Available Apache Virtual Hosts
19      :type vhosts: :class:`list` of type `~obj.Vhost`
20  
21      :returns: VirtualHost or `None`
22      :rtype: `~obj.Vhost` or `None`
23  
24      """
25      if not vhosts:
26          return None
27      while True:
28          code, tag = _vhost_menu(domain, vhosts)
29          if code == display_util.HELP:
30              _more_info_vhost(vhosts[tag])
31          elif code == display_util.OK:
32              return vhosts[tag]
33          else:
34              return None
35  
36  
37  def _vhost_menu(domain, vhosts):
38      """Select an appropriate Apache Vhost.
39  
40      :param vhosts: Available Apache Virtual Hosts
41      :type vhosts: :class:`list` of type `~obj.Vhost`
42  
43      :returns: Display tuple - ('code', tag')
44      :rtype: `tuple`
45  
46      """
47      # Free characters in the line of display text (9 is for ' | ' formatting)
48      free_chars = display_util.WIDTH - len("HTTPS") - len("Enabled") - 9
49  
50      if free_chars < 2:
51          logger.debug("Display size is too small for "
52                       "letsencrypt_apache.display_ops._vhost_menu()")
53          # This runs the edge off the screen, but it doesn't cause an "error"
54          filename_size = 1
55          disp_name_size = 1
56      else:
57          # Filename is a bit more important and probably longer with 000-*
58          filename_size = int(free_chars * .6)
59          disp_name_size = free_chars - filename_size
60  
61      choices = []
62      for vhost in vhosts:
63          if len(vhost.get_names()) == 1:
64              disp_name = next(iter(vhost.get_names()))
65          elif len(vhost.get_names()) == 0:
66              disp_name = ""
67          else:
68              disp_name = "Multiple Names"
69  
70          choices.append(
71              "{fn:{fn_size}s} | {name:{name_size}s} | {https:5s} | "
72              "{active:7s}".format(
73                  fn=os.path.basename(vhost.filep)[:filename_size],
74                  name=disp_name[:disp_name_size],
75                  https="HTTPS" if vhost.ssl else "",
76                  active="Enabled" if vhost.enabled else "",
77                  fn_size=filename_size,
78                  name_size=disp_name_size)
79          )
80  
81      code, tag = zope.component.getUtility(interfaces.IDisplay).menu(
82          "We were unable to find a vhost with a ServerName or Address of {0}.{1}"
83          "Which virtual host would you like to choose?".format(
84              domain, os.linesep),
85          choices, help_label="More Info", ok_label="Select")
86  
87      return code, tag
88  
89  
90  def _more_info_vhost(vhost):
91      zope.component.getUtility(interfaces.IDisplay).notification(
92          "Virtual Host Information:{0}{1}{0}{2}".format(
93              os.linesep, "-" * (display_util.WIDTH - 4), str(vhost)),
94          height=display_util.HEIGHT)