Repository: certbot/certbot

Issue:
certbot-auto 0.9.0 not quiet anymore
I have a cron job set up that runs `sudo /usr/local/bin/certbot-auto renew --quiet` every day. Normally it produces no output but yesterday it updated `certbot-auto` to v0.9.0 and since then I get the following output on every run:

```
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Cert not yet due for renewal
Cert not yet due for renewal
Cert not yet due for renewal
Cert not yet due for renewal
Cert not yet due for renewal
Cert not yet due for renewal
Cert not yet due for renewal
```



Discussion:
Seeing same since certbot-auto self-updated to 0.9.0 yesterday.

Thanks for reporting this. I've repoed the problem and I'm working on a patch. We'll probably do a 0.9.1 release to resolve this.


Resolving patch:
diff --git a/certbot/constants.py b/certbot/constants.py
--- a/certbot/constants.py
+++ b/certbot/constants.py
@@ -37,6 +37,9 @@
 
 """Defaults for CLI flags and `.IConfig` attributes."""
 
+QUIET_LOGGING_LEVEL = logging.WARNING
+"""Logging level to use in quiet mode."""
+
 RENEWER_DEFAULTS = dict(
     renewer_enabled="yes",
     renew_before_expiry="30 days",
diff --git a/certbot/main.py b/certbot/main.py
--- a/certbot/main.py
+++ b/certbot/main.py
@@ -625,14 +625,22 @@ def _cli_log_handler(config, level, fmt):
     return handler
 
 
-def setup_logging(config, cli_handler_factory, logfile):
-    """Setup logging."""
-    file_fmt = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
+def setup_logging(config):
+    """Sets up logging to logfiles and the terminal.
+
+    :param certbot.interface.IConfig config: Configuration object
+
+    """
     cli_fmt = "%(message)s"
-    level = -config.verbose_count * 10
+    file_fmt = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
+    logfile = "letsencrypt.log"
+    if config.quiet:
+        level = constants.QUIET_LOGGING_LEVEL
+    else:
+        level = -config.verbose_count * 10
     file_handler, log_file_path = setup_log_file_handler(
         config, logfile=logfile, fmt=file_fmt)
-    cli_handler = cli_handler_factory(config, level, cli_fmt)
+    cli_handler = _cli_log_handler(config, level, cli_fmt)
 
     # TODO: use fileConfig?
 
@@ -738,7 +746,7 @@ def main(cli_args=sys.argv[1:]):
                             os.geteuid(), config.strict_permissions)
     # Setup logging ASAP, otherwise "No handlers could be found for
     # logger ..." TODO: this should be done before plugins discovery
-    setup_logging(config, _cli_log_handler, logfile='letsencrypt.log')
+    setup_logging(config)
     cli.possible_deprecation_warning(config)
 
     logger.debug("certbot version: %s", certbot.__version__)


Test patch:
diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py
--- a/certbot/tests/main_test.py
+++ b/certbot/tests/main_test.py
@@ -7,8 +7,11 @@
 import mock
 
 from certbot import cli
+from certbot import colored_logging
+from certbot import constants
 from certbot import configuration
 from certbot import errors
+from certbot import log
 from certbot.plugins import disco as plugins_disco
 
 class MainTest(unittest.TestCase):
@@ -80,6 +83,43 @@ def test_ioerror(self, mock_handler):
                           self.config, "test.log", "%s")
 
 
+class SetupLoggingTest(unittest.TestCase):
+    """Tests for certbot.main.setup_logging."""
+
+    def setUp(self):
+        self.config = mock.Mock(
+            logs_dir=tempfile.mkdtemp(),
+            noninteractive_mode=False, quiet=False, text_mode=False,
+            verbose_count=constants.CLI_DEFAULTS['verbose_count'])
+
+    def tearDown(self):
+        shutil.rmtree(self.config.logs_dir)
+
+    @classmethod
+    def _call(cls, *args, **kwargs):
+        from certbot.main import setup_logging
+        return setup_logging(*args, **kwargs)
+
+    @mock.patch('certbot.main.logging.getLogger')
+    def test_defaults(self, mock_get_logger):
+        self._call(self.config)
+
+        cli_handler = mock_get_logger().addHandler.call_args_list[0][0][0]
+        self.assertEqual(cli_handler.level, -self.config.verbose_count * 10)
+        self.assertTrue(
+            isinstance(cli_handler, log.DialogHandler))
+
+    @mock.patch('certbot.main.logging.getLogger')
+    def test_quiet_mode(self, mock_get_logger):
+        self.config.quiet = self.config.noninteractive_mode = True
+        self._call(self.config)
+
+        cli_handler = mock_get_logger().addHandler.call_args_list[0][0][0]
+        self.assertEqual(cli_handler.level, constants.QUIET_LOGGING_LEVEL)
+        self.assertTrue(
+            isinstance(cli_handler, colored_logging.StreamHandler))
+
+
 class MakeOrVerifyCoreDirTest(unittest.TestCase):
     """Tests for certbot.main.make_or_verify_core_dir."""