From 4a4977a54db7ddfa6b5a39c5803d3ef8dfbe7a39 Mon Sep 17 00:00:00 2001 From: Erica Portnoy Date: Thu, 8 Dec 2016 18:27:23 -0800 Subject: [PATCH] Make renew command respect the --cert-name flag (#3880) * Renew command respects --cert-name flag * Error out early if requested cert doesn't exist --- certbot/main.py | 2 +- certbot/renewal.py | 27 ++++++++++++++++++++------- certbot/tests/main_test.py | 10 ++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/certbot/main.py b/certbot/main.py index e3c271162..395790faa 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -632,7 +632,7 @@ def obtain_cert(config, plugins, lineage=None): def renew(config, unused_plugins): """Renew previously-obtained certificates.""" try: - renewal.renew_all_lineages(config) + renewal.handle_renewal_request(config) finally: hooks.post_hook(config, final=True) diff --git a/certbot/renewal.py b/certbot/renewal.py index 064df8bd2..a057a63a9 100644 --- a/certbot/renewal.py +++ b/certbot/renewal.py @@ -38,6 +38,12 @@ def renewal_conf_files(config): """Return /path/to/*.conf in the renewal conf directory""" return glob.glob(os.path.join(config.renewal_configs_dir, "*.conf")) +def renewal_file_for_certname(config, certname): + """Return /path/to/certname.conf in the renewal conf directory""" + path = os.path.join(config.renewal_configs_dir, "{0}.conf".format(certname)) + if not os.path.exists(path): + raise errors.CertStorageError("No certificate found with name {0}.".format(certname)) + return path def _reconstitute(config, full_path): """Try to instantiate a RenewableCert, updating config with relevant items. @@ -296,26 +302,33 @@ def _renew_describe_results(config, renew_successes, renew_failures, print("\n".join(out)) -def renew_all_lineages(config): +def handle_renewal_request(config): """Examine each lineage; renew if due and report results""" # This is trivially False if config.domains is empty - if any(domain not in config.webroot_map for domain in config.domains) or config.certname: + if any(domain not in config.webroot_map for domain in config.domains): # If more plugins start using cli.add_domains, # we may want to only log a warning here - raise errors.Error("Currently, the renew verb is only capable of " + raise errors.Error("Currently, the renew verb is capable of either " "renewing all installed certificates that are due " - "to be renewed; individual domains or lineages cannot be " - "specified with this action. If you would like to " - "renew specific certificates, use the certonly " + "to be renewed or renewing a single certificate specified " + "by its name. If you would like to renew specific " + "certificates by their domains, use the certonly " "command. The renew verb may provide other options " "for selecting certificates to renew in the future.") + renewer_config = configuration.RenewerConfiguration(config) + + if config.certname: + conf_files = [renewal_file_for_certname(renewer_config, config.certname)] + else: + conf_files = renewal_conf_files(renewer_config) + renew_successes = [] renew_failures = [] renew_skipped = [] parse_failures = [] - for renewal_file in renewal_conf_files(renewer_config): + for renewal_file in conf_files: disp = zope.component.getUtility(interfaces.IDisplay) disp.notification("Processing " + renewal_file, pause=False) lineage_config = copy.deepcopy(config) diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 5e1ce1ab5..a0d6cc418 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -872,6 +872,16 @@ class MainTest(unittest.TestCase): # pylint: disable=too-many-public-methods args = ["renew", "--dry-run", "-tvv"] self._test_renewal_common(False, [], args=args, should_renew=False, error_expected=True) + def test_renew_with_certname(self): + test_util.make_lineage(self, 'sample-renewal.conf') + self._test_renewal_common(True, [], should_renew=True, + args=['renew', '--dry-run', '--cert-name', 'sample-renewal']) + + def test_renew_with_bad_certname(self): + self._test_renewal_common(True, [], should_renew=False, + args=['renew', '--dry-run', '--cert-name', 'sample-renewal'], + error_expected=True) + def _make_dummy_renewal_config(self): renewer_configs_dir = os.path.join(self.config_dir, 'renewal') os.makedirs(renewer_configs_dir)