Automatically select among default vhosts if we have a port preference in nginx (#5944)

* automatically select among default vhosts if we have a port preference

* ports should be strings in the nginx plugin

* clarify port vs preferred_port behavior by adding allow_port_mismatch flag

* update all instances of default_vhosts to all_default_vhosts

* require port

* port should never be None in _get_default_vhost
This commit is contained in:
ohemorange
2018-06-05 13:40:48 -07:00
committed by Brad Warren
parent 09a28c7a27
commit d905886f4c
2 changed files with 27 additions and 11 deletions
+20 -11
View File
@@ -289,7 +289,8 @@ class NginxConfigurator(common.Installer):
if not vhosts:
if create_if_no_match:
# result will not be [None] because it errors on failure
vhosts = [self._vhost_from_duplicated_default(target_name)]
vhosts = [self._vhost_from_duplicated_default(target_name, True,
str(self.config.tls_sni_01_port))]
else:
# No matches. Raise a misconfiguration error.
raise errors.MisconfigurationError(
@@ -332,9 +333,12 @@ class NginxConfigurator(common.Installer):
ipv6only_present = True
return (ipv6_active, ipv6only_present)
def _vhost_from_duplicated_default(self, domain, port=None):
def _vhost_from_duplicated_default(self, domain, allow_port_mismatch, port):
"""if allow_port_mismatch is False, only server blocks with matching ports will be
used as a default server block template.
"""
if self.new_vhost is None:
default_vhost = self._get_default_vhost(port, domain)
default_vhost = self._get_default_vhost(domain, allow_port_mismatch, port)
self.new_vhost = self.parser.duplicate_vhost(default_vhost,
remove_singleton_listen_params=True)
self.new_vhost.names = set()
@@ -350,19 +354,24 @@ class NginxConfigurator(common.Installer):
name_block[0].append(name)
self.parser.update_or_add_server_directives(vhost, name_block)
def _get_default_vhost(self, port, domain):
def _get_default_vhost(self, domain, allow_port_mismatch, port):
"""Helper method for _vhost_from_duplicated_default; see argument documentation there"""
vhost_list = self.parser.get_vhosts()
# if one has default_server set, return that one
default_vhosts = []
all_default_vhosts = []
port_matching_vhosts = []
for vhost in vhost_list:
for addr in vhost.addrs:
if addr.default:
if port is None or self._port_matches(port, addr.get_port()):
default_vhosts.append(vhost)
break
all_default_vhosts.append(vhost)
if self._port_matches(port, addr.get_port()):
port_matching_vhosts.append(vhost)
break
if len(default_vhosts) == 1:
return default_vhosts[0]
if len(port_matching_vhosts) == 1:
return port_matching_vhosts[0]
elif len(all_default_vhosts) == 1 and allow_port_mismatch:
return all_default_vhosts[0]
# TODO: present a list of vhosts for user to choose from
@@ -471,7 +480,7 @@ class NginxConfigurator(common.Installer):
matches = self._get_redirect_ranked_matches(target_name, port)
vhosts = [x for x in [self._select_best_name_match(matches)]if x is not None]
if not vhosts and create_if_no_match:
vhosts = [self._vhost_from_duplicated_default(target_name, port=port)]
vhosts = [self._vhost_from_duplicated_default(target_name, False, port)]
return vhosts
def _port_matches(self, test_port, matching_port):
@@ -731,6 +731,13 @@ class NginxConfiguratorTest(util.NginxTest):
"www.nomatch.com", "example/cert.pem", "example/key.pem",
"example/chain.pem", "example/fullchain.pem")
def test_deploy_no_match_multiple_defaults_ok(self):
foo_conf = self.config.parser.abs_path('foo.conf')
self.config.parser.parsed[foo_conf][2][1][0][1][0][1] = '*:5001'
self.config.version = (1, 3, 1)
self.config.deploy_cert("www.nomatch.com", "example/cert.pem", "example/key.pem",
"example/chain.pem", "example/fullchain.pem")
def test_deploy_no_match_add_redirect(self):
default_conf = self.config.parser.abs_path('sites-enabled/default')
foo_conf = self.config.parser.abs_path('foo.conf')