Allow installation if there's no appropriate vhost

This commit is contained in:
Erica Portnoy 2017-09-29 18:34:18 -07:00
parent a805180cee
commit 19235f3cc6
4 changed files with 58 additions and 5 deletions

View file

@ -117,6 +117,9 @@ class NginxConfigurator(common.Installer):
# Files to save
self.save_notes = ""
# For creating new vhosts if no names match
self.new_vhost = None
# Add number of outstanding challenges
self._chall_out = 0
@ -191,9 +194,11 @@ class NginxConfigurator(common.Installer):
"The nginx plugin currently requires --fullchain-path to "
"install a cert.")
vhost = self.choose_vhost(domain)
cert_directives = [['\n', 'ssl_certificate', ' ', fullchain_path],
['\n', 'ssl_certificate_key', ' ', key_path]]
vhost = self.choose_vhost(domain, raise_if_no_match=False)
if vhost is None:
vhost = self._vhost_from_duplicated_default(domain)
cert_directives = [['\n ', 'ssl_certificate', ' ', fullchain_path],
['\n ', 'ssl_certificate_key', ' ', key_path]]
self.parser.add_server_directives(vhost,
cert_directives, replace=True)
@ -250,6 +255,32 @@ class NginxConfigurator(common.Installer):
return vhost
def _vhost_from_duplicated_default(self, domain):
if self.new_vhost is None:
default_vhost = self._get_default_vhost()
self.new_vhost = self.parser.create_new_vhost_from_default(default_vhost)
self.new_vhost.names = set()
import ipdb; ipdb.set_trace()
self.new_vhost.names.add(domain)
name_block = [['\n ', 'server_name', ' ', " ".join(self.new_vhost.names)]]
self.parser.add_server_directives(self.new_vhost, name_block, replace=True)
return self.new_vhost
def _get_default_vhost(self):
vhost_list = self.parser.get_vhosts()
# if one has default_server set, return that one
for vhost in vhost_list:
for addr in vhost.addrs:
if addr.default:
return vhost
# otherwise, return the first one
if len(vhost_list) > 0:
return vhost_list[0]
raise errors.MisconfigurationError("No server blocks found in Nginx configuration.")
def _get_ranked_matches(self, target_name):
"""Returns a ranked list of vhosts that match target_name.
The ranking gives preference to SSL vhosts.

View file

@ -235,8 +235,8 @@ class UnspacedList(list):
self.dirty = True
def __deepcopy__(self, memo):
l = UnspacedList(self[:])
l.spaced = copy.deepcopy(self.spaced, memo=memo)
new_spaced = copy.deepcopy(self.spaced, memo=memo)
l = UnspacedList(new_spaced)
l.dirty = self.dirty
return l

View file

@ -1,4 +1,5 @@
"""Module contains classes used by the Nginx Configurator."""
import copy
import re
import six
@ -125,6 +126,9 @@ class Addr(common.Addr):
self.default == other.default)
return False
def copy(self):
return Addr.fromstring(str(self))
class VirtualHost(object): # pylint: disable=too-few-public-methods
"""Represents an Nginx Virtualhost.

View file

@ -312,6 +312,24 @@ class NginxParser(object):
except errors.MisconfigurationError as err:
raise errors.MisconfigurationError("Problem in %s: %s" % (filename, str(err)))
def create_new_vhost_from_default(self, vhost_template):
# TODO: do the right thing for debian
# put it in the same file as the template, at the same level
enclosing_block = self.parsed[vhost_template.filep]
for index in vhost_template.path[:-1]:
enclosing_block = enclosing_block[index]
new_location = vhost_template.path[-1] + 1
raw_in_parsed = copy.deepcopy(enclosing_block[vhost_template.path[-1]])
enclosing_block.insert(new_location, raw_in_parsed)
new_vhost = copy.deepcopy(vhost_template)
new_vhost.path[-1] = new_location
for addr in new_vhost.addrs:
addr.default = False
for directive in enclosing_block[new_vhost.path[-1]][1]:
if len(directive) > 0 and directive[0] == 'listen' and 'default_server' in directive:
del directive[directive.index('default_server')]
return new_vhost
def _parse_ssl_options(ssl_options):
if ssl_options is not None:
try: