diff --git a/letsencrypt/cli.py b/letsencrypt/cli.py index 669bed7c7..09a9646e0 100644 --- a/letsencrypt/cli.py +++ b/letsencrypt/cli.py @@ -1261,11 +1261,10 @@ def _plugins_parsing(helpful, plugins): "handle different domains; each domain will have the webroot path that" " preceded it. For instance: `-w /var/www/example -d example.com -d " "www.example.com -w /var/www/thing -d thing.net -d m.thing.net`") - parse_dict = lambda s: dict(json.loads(s)) # --webroot-map still has some awkward properties, so it is undocumented - helpful.add("webroot", "--webroot-map", default={}, type=parse_dict, - help="JSON dictionary mapping domains to webroot paths; this implies -d for each entry.") - + helpful.add("webroot", "--webroot-map", default={}, action=WebrootMapProcessor, + help="JSON dictionary mapping domains to webroot paths; this implies -d " + "for each entry.") class WebrootPathProcessor(argparse.Action): # pylint: disable=missing-docstring def __init__(self, *args, **kwargs): @@ -1293,27 +1292,39 @@ class WebrootPathProcessor(argparse.Action): # pylint: disable=missing-docstring "them must precede all domain flags") config.webroot_path.append(webroot) +_undot = lambda domain : domain[:-1] if domain.endswith('.') else domain -def _process_domain(config, domain_arg): +def _process_domain(config, domain_arg, webroot_path=None): """ Process a new -d flag, helping the webroot plugin construct a map of {domain : webrootpath} if -w / --webroot-path is in use """ + webroot_path = webroot_path if webroot_path else config.webroot_path + for domain in (d.strip() for d in domain_arg.split(",")): if domain not in config.domains: + domain = _undot(domain) config.domains.append(domain) # Each domain has a webroot_path of the most recent -w flag # unless it was explicitly included in webroot_map - if config.webroot_path: + if webroot_path: config.webroot_map.setdefault(domain, config.webroot_path[-1]) +class WebrootMapProcessor(argparse.Action): # pylint: disable=missing-docstring + def __call__(self, parser, config, webroot_map_arg, option_string=None): + webroot_map = json.loads(webroot_map_arg) + for domains, webroot_path in webroot_map.iteritems(): + _process_domain(config, domains, webroot) + + class DomainFlagProcessor(argparse.Action): # pylint: disable=missing-docstring def __call__(self, parser, config, domain_arg, option_string=None): """Just wrap _process_domain in argparseese.""" _process_domain(config, domain_arg) + def setup_log_file_handler(args, logfile, fmt): """Setup file debug logging.""" log_file_path = os.path.join(args.logs_dir, logfile) diff --git a/letsencrypt/tests/cli_test.py b/letsencrypt/tests/cli_test.py index 6c8facd81..ac8932112 100644 --- a/letsencrypt/tests/cli_test.py +++ b/letsencrypt/tests/cli_test.py @@ -356,6 +356,10 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods namespace = cli.prepare_and_parse_args(plugins, short_args) self.assertEqual(namespace.domains, ['example.com']) + short_args = ['-d', 'trailing.period.com.'] + namespace = cli.prepare_and_parse_args(plugins, short_args) + self.assertEqual(namespace.domains, ['trailing.period.com']) + short_args = ['-d', 'example.com,another.net,third.org,example.com'] namespace = cli.prepare_and_parse_args(plugins, short_args) self.assertEqual(namespace.domains, ['example.com', 'another.net', @@ -365,6 +369,10 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods namespace = cli.prepare_and_parse_args(plugins, long_args) self.assertEqual(namespace.domains, ['example.com']) + long_args = ['--domains', 'trailing.period.com.'] + namespace = cli.prepare_and_parse_args(plugins, long_args) + self.assertEqual(namespace.domains, ['trailing.period.com']) + long_args = ['--domains', 'example.com,another.net,example.com'] namespace = cli.prepare_and_parse_args(plugins, long_args) self.assertEqual(namespace.domains, ['example.com', 'another.net']) @@ -401,7 +409,7 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods plugins = disco.PluginsRegistry.find_all() webroot_args = ['--webroot', '-w', '/var/www/example', '-d', 'example.com,www.example.com', '-w', '/var/www/superfluous', - '-d', 'superfluo.us', '-d', 'www.superfluo.us'] + '-d', 'superfluo.us', '-d', 'www.superfluo.us.'] namespace = cli.prepare_and_parse_args(plugins, webroot_args) self.assertEqual(namespace.webroot_map, { 'example.com': '/var/www/example', @@ -430,6 +438,11 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods extra_args = ['-c', test_util.vector_path('webrootconftest.ini')] self._webroot_map_test(None, None, None, expected_map, domains, extra_args) + webroot_map_args = ['--webroot-map', + '{"eg.com.,www.eg.com": "/tmp", "eg.is.": "/tmp2"}'] + namespace = cli.prepare_and_parse_args(plugins, webroot_map_args) + self.assertEqual(namespace.webroot_map, + {u"eg.com": u"/tmp", u"www.eg.com": u"/tmp", u"eg.is": "/tmp2"}) @mock.patch('letsencrypt.cli._suggest_donate') @mock.patch('letsencrypt.crypto_util.notAfter')