Compare commits

...

10 Commits

Author SHA1 Message Date
Brad Warren
d9a2612d21 Release 0.14.2 2017-05-25 14:23:35 -07:00
Brad Warren
fbd0325673 Fixes #4719 (#4737) (#4740)
* Automatically delete temp log file when not used.

This allows close() calls in logging.shutdown() to cause the file to be
deleted when no logging output has been written to the file.

* Make certbot.log.MemoryHandler.flush() a noop.

This causes MemoryHandler.flush() calls in logging.shutdown to be a noop,
allowing us to control when the handler is actually flushed. This prevents log
records from being sent to a temporary file handler for things like
`certbot --version`.

* Keep reference to certbot.log.MemoryHandler.target

In Python 2.7+, the logging module only keeps weak references to created
logging handlers. Because of this, the MemoryHandler's target will not be
properly flushed and closed when logging.shutdown() is called on program exit
unless we keep a reference to it in the MemoryHandler.

* Fixes #4719.

This completes the changes necessary to fix #4719. Now temporary log files are
not created if sys.exit() is called before logging is fully set up. These files
are still created if Certbot crashes for any other reason.

* Document pre_arg_parse_except_hook args.

(cherry picked from commit 93310fe67c)
2017-05-25 14:07:40 -07:00
Brad Warren
c5d11d333f Merge pull request #4674 from certbot/0.14.x+1
Release 0.14.1
2017-05-16 14:33:43 -07:00
Brad Warren
78e3bd6e8c Release 0.14.1 2017-05-16 10:03:51 -07:00
ohemorange
44ab49bcd6 Allow Nginx to insert include files with comments inside (#4666) (#4668)
* add failing test case

* allow include files to insert comments

* lint
2017-05-15 18:04:16 -07:00
Brad Warren
98905fd470 Merge pull request #4669 from certbot/0.14.x-stuff
0.14.x stuff
2017-05-15 17:00:15 -07:00
Brad Warren
8c313449f9 Make 42d07d7 more closely follow repo conventions
(cherry picked from commit d467295d2a)
2017-05-15 15:40:04 -07:00
Joona Hoikkala
b33669edac Force augeas file reload to recalculate span indicies
(cherry picked from commit f5b61d56bd)
2017-05-15 15:39:55 -07:00
Brad Warren
25d9fbd657 Modify special action types only once
(cherry picked from commit 65f7f3e12b)
2017-05-15 15:39:18 -07:00
Ryan Pineo
7cbbf20b0c support version 0.12.0 of configargparse
fixes #4648

(cherry picked from commit 42d07d756d)
2017-05-15 15:39:12 -07:00
22 changed files with 293 additions and 105 deletions

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.14.0'
version = '0.14.2'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -120,8 +120,8 @@ class AugeasConfigurator(common.Plugin):
# If the augeas tree didn't change, no files were saved and a backup
# should not be created
save_files = set()
if save_paths:
save_files = set()
for path in save_paths:
save_files.add(self.aug.get(path)[6:])
@@ -140,6 +140,12 @@ class AugeasConfigurator(common.Plugin):
self.save_notes = ""
self.aug.save()
# Force reload if files were modified
# This is needed to recalculate augeas directive span
if save_files:
for sf in save_files:
self.aug.remove("/files/"+sf)
self.aug.load()
if title and not temporary:
try:
self.reverter.finalize_checkpoint(title)

View File

@@ -1065,8 +1065,28 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
span_end = span_val[6]
with open(span_filep, 'r') as fh:
fh.seek(span_start)
vh_contents = fh.read(span_end-span_start)
return vh_contents.split("\n")
vh_contents = fh.read(span_end-span_start).split("\n")
self._remove_closing_vhost_tag(vh_contents)
return vh_contents
def _remove_closing_vhost_tag(self, vh_contents):
"""Removes the closing VirtualHost tag if it exists.
This method modifies vh_contents directly to remove the closing
tag. If the closing vhost tag is found, everything on the line
after it is also removed. Whether or not this tag is included
in the result of span depends on the Augeas version.
:param list vh_contents: VirtualHost block contents to check
"""
for offset, line in enumerate(reversed(vh_contents)):
if line:
line_index = line.lower().find("</virtualhost>")
if line_index != -1:
content_index = len(vh_contents) - offset - 1
vh_contents[content_index] = line[:line_index]
break
def _update_ssl_vhosts_addrs(self, vh_path):
ssl_addrs = set()

View File

@@ -597,6 +597,21 @@ class MultipleVhostsTest(util.ApacheTest):
# already listens to the correct port
self.assertEqual(mock_add_dir.call_count, 0)
def test_make_vhost_ssl_with_mock_span(self):
# span excludes the closing </VirtualHost> tag in older versions
# of Augeas
return_value = [self.vh_truth[0].filep, 1, 12, 0, 0, 0, 1142]
with mock.patch.object(self.config.aug, 'span') as mock_span:
mock_span.return_value = return_value
self.test_make_vhost_ssl()
def test_make_vhost_ssl_with_mock_span2(self):
# span includes the closing </VirtualHost> tag in newer versions
# of Augeas
return_value = [self.vh_truth[0].filep, 1, 12, 0, 0, 0, 1157]
with mock.patch.object(self.config.aug, 'span') as mock_span:
mock_span.return_value = return_value
self.test_make_vhost_ssl()
def test_make_vhost_ssl(self):
ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0])

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.14.0'
version = '0.14.2'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -28,7 +28,7 @@ if [ -z "$VENV_PATH" ]; then
VENV_PATH="$XDG_DATA_HOME/$VENV_NAME"
fi
VENV_BIN="$VENV_PATH/bin"
LE_AUTO_VERSION="0.14.0"
LE_AUTO_VERSION="0.14.2"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -860,18 +860,18 @@ letsencrypt==0.7.0 \
# THE LINES BELOW ARE EDITED BY THE RELEASE SCRIPT; ADD ALL DEPENDENCIES ABOVE.
acme==0.14.0 \
--hash=sha256:fca8766a2596833e8886f7ef72cf82d1f6c6cffa895781a5676861c251b24b70 \
--hash=sha256:ce7d2bca31e85adac1030c944e0a9d96e8b0f85cdc616b78d40eb09c91803543
certbot==0.14.0 \
--hash=sha256:071790b1ec4e5b94aa1688f8a62a10905c28438cd55d990cdb8c9f733d3a4a41 \
--hash=sha256:98add3721e1edaedb404879a9d39bd49020e94fc8eedbc46032a00ada51d7741
certbot-apache==0.14.0 \
--hash=sha256:ab837efce7aa4c4e47a724a60dcbeacadb9dfe64bd1d32a4e854678c4fcd82a3 \
--hash=sha256:bbcd21d9f3fd8cdc4453ef94d0cb6033c3a19f879dcd314231501ebb7180168f
certbot-nginx==0.14.0 \
--hash=sha256:608b2f6f2b04ce93c503a95ffba4f0e0ca2e0cb9ea587a8376368fa621b388e4 \
--hash=sha256:86e964b2a7818cc165d913e27e504f2ef2f60750ab0db6d39bfb3465d54c30db
acme==0.14.2 \
--hash=sha256:b3068d360beccd3b23a81d7cd2522437d847328811b573a5fe14eb04147667cf \
--hash=sha256:166b7f4858f5b144b03236b995b787a9da1e410121fb7dcac9c7d3b594bc6fcd
certbot==0.14.2 \
--hash=sha256:525e15e43c833db9a9934308d69dcdd220fa799488cd84543748671c68aba73d \
--hash=sha256:5bc8547dcfc0fc587e15253e264f79d8397e48bfbc8697d5aca87eae978769ac
certbot-apache==0.14.2 \
--hash=sha256:15647d424a5a7e4c44c684324ac07a457a2e0d61fce1acaa421c0b641941a350 \
--hash=sha256:e5220d3e6ee5114b41b398110dfbd8f13bd1e8c7902758634449e0b4ae515b76
certbot-nginx==0.14.2 \
--hash=sha256:231377fbdfb6303adddc73fe3f856b9fb6d0175db825650e39fe3dfd6a58f8ef \
--hash=sha256:529a18280acf41f5f7e0fe7d82c0a5d4d197d14f82742eaec54bb1d3f69c325a
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.14.0'
version = '0.14.2'
install_requires = [
'certbot',

View File

@@ -529,7 +529,10 @@ def _add_directive(block, directive, replace):
"""
directive = nginxparser.UnspacedList(directive)
if len(directive) == 0 or directive[0] == '#':
def is_whitespace_or_comment(directive):
"""Is this directive either a whitespace or comment directive?"""
return len(directive) == 0 or directive[0] == '#'
if is_whitespace_or_comment(directive):
# whitespace or comment
block.append(directive)
return
@@ -574,7 +577,8 @@ def _add_directive(block, directive, replace):
for included_directive in included_directives:
included_dir_loc = find_location(included_directive)
included_dir_name = included_directive[0]
if not can_append(included_dir_loc, included_dir_name):
if not is_whitespace_or_comment(included_directive) \
and not can_append(included_dir_loc, included_dir_name):
if block[included_dir_loc] != included_directive:
raise errors.MisconfigurationError(err_fmt.format(included_directive,
block[included_dir_loc]))

View File

@@ -13,7 +13,7 @@ from certbot_nginx import parser
from certbot_nginx.tests import util
class NginxParserTest(util.NginxTest):
class NginxParserTest(util.NginxTest): #pylint: disable=too-many-public-methods
"""Nginx Parser Test."""
def setUp(self):
@@ -230,6 +230,33 @@ class NginxParserTest(util.NginxTest):
['ssl_certificate', '/etc/ssl/cert2.pem']],
replace=False)
def test_comment_is_repeatable(self):
nparser = parser.NginxParser(self.config_path)
example_com = nparser.abs_path('sites-enabled/example.com')
mock_vhost = obj.VirtualHost(example_com,
None, None, None,
set(['.example.com', 'example.*']),
None, [0])
nparser.add_server_directives(mock_vhost,
[['\n ', '#', ' ', 'what a nice comment']],
replace=False)
nparser.add_server_directives(mock_vhost,
[['\n ', 'include', ' ',
nparser.abs_path('comment_in_file.conf')]],
replace=False)
from certbot_nginx.parser import COMMENT
self.assertEqual(nparser.parsed[example_com],
[[['server'], [['listen', '69.50.225.155:9000'],
['listen', '127.0.0.1'],
['server_name', '.example.com'],
['server_name', 'example.*'],
['#', ' ', 'what a nice comment'],
[],
['include', nparser.abs_path('comment_in_file.conf')],
['#', COMMENT],
[]]]]
)
def test_replace_server_directives(self):
nparser = parser.NginxParser(self.config_path)
target = set(['.example.com', 'example.*'])

View File

@@ -0,0 +1 @@
# a comment inside a file

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages
version = '0.14.0'
version = '0.14.2'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -1,4 +1,4 @@
"""Certbot client."""
# version number like 1.2.3a0, must have at least 2 parts, like 1.2
__version__ = '0.14.0'
__version__ = '0.14.2'

View File

@@ -70,7 +70,8 @@ def pre_arg_parse_setup():
# close() are explicitly called
util.atexit_register(logging.shutdown)
sys.excepthook = functools.partial(
except_hook, debug='--debug' in sys.argv, log_path=temp_handler.path)
pre_arg_parse_except_hook, memory_handler,
debug='--debug' in sys.argv, log_path=temp_handler.path)
def post_arg_parse_setup(config):
@@ -103,8 +104,9 @@ def post_arg_parse_setup(config):
root_logger.removeHandler(memory_handler)
temp_handler = memory_handler.target
memory_handler.setTarget(file_handler)
memory_handler.flush(force=True)
memory_handler.close()
temp_handler.delete_and_close()
temp_handler.close()
if config.quiet:
level = constants.QUIET_LOGGING_LEVEL
@@ -115,7 +117,7 @@ def post_arg_parse_setup(config):
logger.info('Saving debug log to %s', file_path)
sys.excepthook = functools.partial(
except_hook, debug=config.debug, log_path=logs_dir)
post_arg_parse_except_hook, debug=config.debug, log_path=logs_dir)
def setup_log_file_handler(config, logfile, fmt):
@@ -194,8 +196,7 @@ class MemoryHandler(logging.handlers.MemoryHandler):
"""Buffers logging messages in memory until the buffer is flushed.
This differs from `logging.handlers.MemoryHandler` in that flushing
only happens when it is done explicitly by calling flush() or
close().
only happens when flush(force=True) is called.
"""
def __init__(self, target=None):
@@ -209,6 +210,33 @@ class MemoryHandler(logging.handlers.MemoryHandler):
else:
super(MemoryHandler, self).__init__(capacity, target=target)
def close(self):
"""Close the memory handler, but don't set the target to None."""
# This allows the logging module which may only have a weak
# reference to the target handler to properly flush and close it.
target = self.target
if sys.version_info < (2, 7): # pragma: no cover
logging.handlers.MemoryHandler.close(self)
else:
super(MemoryHandler, self).close()
self.target = target
def flush(self, force=False): # pylint: disable=arguments-differ
"""Flush the buffer if force=True.
If force=False, this call is a noop.
:param bool force: True if the buffer should be flushed.
"""
# This method allows flush() calls in logging.shutdown to be a
# noop so we can control when this handler is flushed.
if force:
if sys.version_info < (2, 7): # pragma: no cover
logging.handlers.MemoryHandler.flush(self)
else:
super(MemoryHandler, self).flush()
def shouldFlush(self, record):
"""Should the buffer be automatically flushed?
@@ -224,7 +252,9 @@ class MemoryHandler(logging.handlers.MemoryHandler):
class TempHandler(logging.StreamHandler):
"""Safely logs messages to a temporary file.
The file is created with permissions 600.
The file is created with permissions 600. If no log records are sent
to this handler, the temporary file is deleted when the handler is
closed.
:ivar str path: file system path to the temporary log file
@@ -238,19 +268,26 @@ class TempHandler(logging.StreamHandler):
else:
super(TempHandler, self).__init__(stream)
self.path = stream.name
self._delete = True
def delete_and_close(self):
"""Close the handler and delete the temporary log file."""
self._close(delete=True)
def emit(self, record):
"""Log the specified logging record.
:param logging.LogRecord record: Record to be formatted
"""
self._delete = False
# logging handlers use old style classes in Python 2.6 so
# super() cannot be used
if sys.version_info < (2, 7): # pragma: no cover
logging.StreamHandler.emit(self, record)
else:
super(TempHandler, self).emit(record)
def close(self):
"""Close the handler and the temporary log file."""
self._close(delete=False)
def _close(self, delete):
"""Close the handler and the temporary log file.
:param bool delete: True if the log file should be deleted
The temporary log file is deleted if it wasn't used.
"""
self.acquire()
@@ -258,8 +295,9 @@ class TempHandler(logging.StreamHandler):
# StreamHandler.close() doesn't close the stream to allow a
# stream like stderr to be used
self.stream.close()
if delete:
if self._delete:
os.remove(self.path)
self._delete = False
if sys.version_info < (2, 7): # pragma: no cover
logging.StreamHandler.close(self)
else:
@@ -268,7 +306,34 @@ class TempHandler(logging.StreamHandler):
self.release()
def except_hook(exc_type, exc_value, trace, debug, log_path):
def pre_arg_parse_except_hook(memory_handler, *args, **kwargs):
"""A simple wrapper around post_arg_parse_except_hook.
The additional functionality provided by this wrapper is the memory
handler will be flushed before Certbot exits. This allows us to
write logging messages to a temporary file if we crashed before
logging was fully configured.
Since sys.excepthook isn't called on SystemExit exceptions, the
memory handler will not be flushed in this case which prevents us
from creating temporary log files when argparse exits because a
command line argument was invalid or -h, --help, or --version was
provided on the command line.
:param MemoryHandler memory_handler: memory handler to flush
:param tuple args: args for post_arg_parse_except_hook
:param dict kwargs: kwargs for post_arg_parse_except_hook
"""
try:
post_arg_parse_except_hook(*args, **kwargs)
finally:
# flush() is called here so messages logged during
# post_arg_parse_except_hook are also flushed.
memory_handler.flush(force=True)
def post_arg_parse_except_hook(exc_type, exc_value, trace, debug, log_path):
"""Logs fatal exceptions and reports them to the user.
If debug is True, the full exception and traceback is shown to the

View File

@@ -26,7 +26,7 @@ class PreArgParseSetupTest(unittest.TestCase):
return pre_arg_parse_setup(*args, **kwargs)
@mock.patch('certbot.log.sys')
@mock.patch('certbot.log.except_hook')
@mock.patch('certbot.log.pre_arg_parse_except_hook')
@mock.patch('certbot.log.logging.getLogger')
@mock.patch('certbot.log.util.atexit_register')
def test_it(self, mock_register, mock_get, mock_except_hook, mock_sys):
@@ -34,11 +34,6 @@ class PreArgParseSetupTest(unittest.TestCase):
mock_sys.version_info = sys.version_info
self._call()
mock_register.assert_called_once_with(logging.shutdown)
mock_sys.excepthook(1, 2, 3)
mock_except_hook.assert_called_once_with(
1, 2, 3, debug=True, log_path=mock.ANY)
mock_root_logger = mock_get()
mock_root_logger.setLevel.assert_called_once_with(logging.DEBUG)
self.assertEqual(mock_root_logger.addHandler.call_count, 2)
@@ -54,6 +49,11 @@ class PreArgParseSetupTest(unittest.TestCase):
self.assertTrue(
isinstance(memory_handler.target, logging.StreamHandler))
mock_register.assert_called_once_with(logging.shutdown)
mock_sys.excepthook(1, 2, 3)
mock_except_hook.assert_called_once_with(
memory_handler, 1, 2, 3, debug=True, log_path=mock.ANY)
class PostArgParseSetupTest(test_util.TempDirTestCase):
"""Tests for certbot.log.post_arg_parse_setup."""
@@ -88,7 +88,8 @@ class PostArgParseSetupTest(test_util.TempDirTestCase):
def test_common(self):
with mock.patch('certbot.log.logging.getLogger') as mock_get_logger:
mock_get_logger.return_value = self.root_logger
with mock.patch('certbot.log.except_hook') as mock_except_hook:
except_hook_path = 'certbot.log.post_arg_parse_except_hook'
with mock.patch(except_hook_path) as mock_except_hook:
with mock.patch('certbot.log.sys') as mock_sys:
mock_sys.version_info = sys.version_info
self._call(self.config)
@@ -203,12 +204,13 @@ class MemoryHandlerTest(unittest.TestCase):
def test_flush(self):
self._test_log_debug()
self.handler.flush()
self.handler.flush(force=True)
self.assertEqual(self.stream.getvalue(), self.msg + '\n')
def test_not_flushed(self):
# By default, logging.ERROR messages and higher are flushed
self.logger.critical(self.msg)
self.handler.flush()
self.assertEqual(self.stream.getvalue(), '')
def test_target_reset(self):
@@ -217,7 +219,7 @@ class MemoryHandlerTest(unittest.TestCase):
new_stream = six.StringIO()
new_stream_handler = logging.StreamHandler(new_stream)
self.handler.setTarget(new_stream_handler)
self.handler.flush()
self.handler.flush(force=True)
self.assertEqual(self.stream.getvalue(), '')
self.assertEqual(new_stream.getvalue(), self.msg + '\n')
new_stream_handler.close()
@@ -234,31 +236,50 @@ class TempHandlerTest(unittest.TestCase):
self.handler = TempHandler()
def tearDown(self):
if not self.closed:
self.handler.delete_and_close()
self.handler.close()
def test_permissions(self):
self.assertTrue(
util.check_permissions(self.handler.path, 0o600, os.getuid()))
def test_delete(self):
self.handler.delete_and_close()
self.closed = True
self.handler.close()
self.assertFalse(os.path.exists(self.handler.path))
def test_no_delete(self):
self.handler.emit(mock.MagicMock())
self.handler.close()
self.closed = True
self.assertTrue(os.path.exists(self.handler.path))
os.remove(self.handler.path)
class ExceptHookTest(unittest.TestCase):
"""Tests for certbot.log.except_hook."""
class PreArgParseExceptHookTest(unittest.TestCase):
"""Tests for certbot.log.pre_arg_parse_except_hook."""
@classmethod
def _call(cls, *args, **kwargs):
from certbot.log import except_hook
return except_hook(*args, **kwargs)
from certbot.log import pre_arg_parse_except_hook
return pre_arg_parse_except_hook(*args, **kwargs)
@mock.patch('certbot.log.post_arg_parse_except_hook')
def test_it(self, mock_post_arg_parse_except_hook):
# pylint: disable=star-args
memory_handler = mock.MagicMock()
args = ('some', 'args',)
kwargs = {'some': 'kwargs'}
self._call(memory_handler, *args, **kwargs)
mock_post_arg_parse_except_hook.assert_called_once_with(
*args, **kwargs)
memory_handler.flush.assert_called_once_with(force=True)
class PostArgParseExceptHookTest(unittest.TestCase):
"""Tests for certbot.log.post_arg_parse_except_hook."""
@classmethod
def _call(cls, *args, **kwargs):
from certbot.log import post_arg_parse_except_hook
return post_arg_parse_except_hook(*args, **kwargs)
def setUp(self):
self.error_msg = 'test error message'

View File

@@ -368,6 +368,29 @@ class AddDeprecatedArgumentTest(unittest.TestCase):
pass
self.assertTrue("--old-option" not in stdout.getvalue())
def test_set_constant(self):
"""Test when ACTION_TYPES_THAT_DONT_NEED_A_VALUE is a set.
This variable is a set in configargparse versions < 0.12.0.
"""
self._test_constant_common(set)
def test_tuple_constant(self):
"""Test when ACTION_TYPES_THAT_DONT_NEED_A_VALUE is a tuple.
This variable is a tuple in configargparse versions >= 0.12.0.
"""
self._test_constant_common(tuple)
def _test_constant_common(self, typ):
with mock.patch("certbot.util.configargparse") as mock_configargparse:
mock_configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE = typ()
self._call("--old-option", 1)
self.assertEqual(
len(mock_configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE), 1)
class EnforceLeValidity(unittest.TestCase):
"""Test enforce_le_validity."""

View File

@@ -476,7 +476,13 @@ def add_deprecated_argument(add_argument, argument_name, nargs):
sys.stderr.write(
"Use of {0} is deprecated.\n".format(option_string))
configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE.add(ShowWarning)
# In version 0.12.0 ACTION_TYPES_THAT_DONT_NEED_A_VALUE was changed from a
# set to a tuple.
if isinstance(configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE, set):
# pylint: disable=no-member
configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE.add(ShowWarning)
else:
configargparse.ACTION_TYPES_THAT_DONT_NEED_A_VALUE += (ShowWarning,)
add_argument(argument_name, action=ShowWarning,
help=argparse.SUPPRESS, nargs=nargs)

View File

@@ -89,7 +89,7 @@ optional arguments:
case, and to know when to deprecate support for past
Python versions and flags. If you wish to hide this
information from the Let's Encrypt server, set this to
"". (default: CertbotACMEClient/0.14.0 (certbot;
"". (default: CertbotACMEClient/0.14.2 (certbot;
Ubuntu 16.04.2 LTS) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/2.7.12). The flags
encoded in the user agent are: --duplicate, --force-

View File

@@ -28,7 +28,7 @@ if [ -z "$VENV_PATH" ]; then
VENV_PATH="$XDG_DATA_HOME/$VENV_NAME"
fi
VENV_BIN="$VENV_PATH/bin"
LE_AUTO_VERSION="0.14.0"
LE_AUTO_VERSION="0.14.2"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -860,18 +860,18 @@ letsencrypt==0.7.0 \
# THE LINES BELOW ARE EDITED BY THE RELEASE SCRIPT; ADD ALL DEPENDENCIES ABOVE.
acme==0.14.0 \
--hash=sha256:fca8766a2596833e8886f7ef72cf82d1f6c6cffa895781a5676861c251b24b70 \
--hash=sha256:ce7d2bca31e85adac1030c944e0a9d96e8b0f85cdc616b78d40eb09c91803543
certbot==0.14.0 \
--hash=sha256:071790b1ec4e5b94aa1688f8a62a10905c28438cd55d990cdb8c9f733d3a4a41 \
--hash=sha256:98add3721e1edaedb404879a9d39bd49020e94fc8eedbc46032a00ada51d7741
certbot-apache==0.14.0 \
--hash=sha256:ab837efce7aa4c4e47a724a60dcbeacadb9dfe64bd1d32a4e854678c4fcd82a3 \
--hash=sha256:bbcd21d9f3fd8cdc4453ef94d0cb6033c3a19f879dcd314231501ebb7180168f
certbot-nginx==0.14.0 \
--hash=sha256:608b2f6f2b04ce93c503a95ffba4f0e0ca2e0cb9ea587a8376368fa621b388e4 \
--hash=sha256:86e964b2a7818cc165d913e27e504f2ef2f60750ab0db6d39bfb3465d54c30db
acme==0.14.2 \
--hash=sha256:b3068d360beccd3b23a81d7cd2522437d847328811b573a5fe14eb04147667cf \
--hash=sha256:166b7f4858f5b144b03236b995b787a9da1e410121fb7dcac9c7d3b594bc6fcd
certbot==0.14.2 \
--hash=sha256:525e15e43c833db9a9934308d69dcdd220fa799488cd84543748671c68aba73d \
--hash=sha256:5bc8547dcfc0fc587e15253e264f79d8397e48bfbc8697d5aca87eae978769ac
certbot-apache==0.14.2 \
--hash=sha256:15647d424a5a7e4c44c684324ac07a457a2e0d61fce1acaa421c0b641941a350 \
--hash=sha256:e5220d3e6ee5114b41b398110dfbd8f13bd1e8c7902758634449e0b4ae515b76
certbot-nginx==0.14.2 \
--hash=sha256:231377fbdfb6303adddc73fe3f856b9fb6d0175db825650e39fe3dfd6a58f8ef \
--hash=sha256:529a18280acf41f5f7e0fe7d82c0a5d4d197d14f82742eaec54bb1d3f69c325a
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQEcBAABCAAGBQJZC76WAAoJEE0XyZXNl3XyXhcIAJ1+gPoWZmXjFcC4by2tDBoM
Lkxf5BNxq8aq7qSohU8SqSo6ShDkWh9ci390n+jbOX1R503uQL1egGbEAJbziFYq
vym6j0AmqM+2/YcWmcj3J7RYtDOV1sUPKD2pgUxWtvQrd9iZ1235WMzBF/uBprzm
qAtFwF04V2H3kkC4e7+jAEkFzs1TJ8fYumqqqw0NgSwM6bikfurpRyf8qR2RVYWt
e3GOTxyBVbjhp2UPy/O8Xx7iBD3m+t9mJgsCJ9l8s7xKot6LF7+WrJkn0A3cfKcR
LSTataKedsP3u1jOgP3y2ujumBlDlDRuXn6vK/YKNYNnHte5B9mstSzoDGgRvHE=
=3Jgs
iQEcBAABCAAGBQJZJ0tAAAoJEE0XyZXNl3Xyta0H/3+UZ1xeCc7CjZBMEMjb6IPm
h0KhptkLfwRR0/vGhTeIaOi8rzZYPuzZVwRvTuJ30oORI/zP+siGTOVW4Rt/3KI0
IZidCJkdl3259jtJpSR9dWOXVp8bklZin8k6daQjbizq8Hl6z0aFLbHlqeSAZhUX
ush94CQwB380OUBut+g3CYx4BxD0dgTODPIaVYzeG8lOX5SXAaBbH79BOAtCr9Hy
sRfYjcBo4aL3rPCayPn+ETvQsYYo/Z7zqHjfShiKzZXNtW+RBGXAf8CGoEk7LKM4
jts6PxOpg2BFpArDKHn6JIWsHOphBAQ/qIIgvD1mKZj6P4hGBJv4+aZ3Q8uhHeg=
=56Pv
-----END PGP SIGNATURE-----

View File

@@ -28,7 +28,7 @@ if [ -z "$VENV_PATH" ]; then
VENV_PATH="$XDG_DATA_HOME/$VENV_NAME"
fi
VENV_BIN="$VENV_PATH/bin"
LE_AUTO_VERSION="0.14.0"
LE_AUTO_VERSION="0.14.2"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -860,18 +860,18 @@ letsencrypt==0.7.0 \
# THE LINES BELOW ARE EDITED BY THE RELEASE SCRIPT; ADD ALL DEPENDENCIES ABOVE.
acme==0.14.0 \
--hash=sha256:fca8766a2596833e8886f7ef72cf82d1f6c6cffa895781a5676861c251b24b70 \
--hash=sha256:ce7d2bca31e85adac1030c944e0a9d96e8b0f85cdc616b78d40eb09c91803543
certbot==0.14.0 \
--hash=sha256:071790b1ec4e5b94aa1688f8a62a10905c28438cd55d990cdb8c9f733d3a4a41 \
--hash=sha256:98add3721e1edaedb404879a9d39bd49020e94fc8eedbc46032a00ada51d7741
certbot-apache==0.14.0 \
--hash=sha256:ab837efce7aa4c4e47a724a60dcbeacadb9dfe64bd1d32a4e854678c4fcd82a3 \
--hash=sha256:bbcd21d9f3fd8cdc4453ef94d0cb6033c3a19f879dcd314231501ebb7180168f
certbot-nginx==0.14.0 \
--hash=sha256:608b2f6f2b04ce93c503a95ffba4f0e0ca2e0cb9ea587a8376368fa621b388e4 \
--hash=sha256:86e964b2a7818cc165d913e27e504f2ef2f60750ab0db6d39bfb3465d54c30db
acme==0.14.2 \
--hash=sha256:b3068d360beccd3b23a81d7cd2522437d847328811b573a5fe14eb04147667cf \
--hash=sha256:166b7f4858f5b144b03236b995b787a9da1e410121fb7dcac9c7d3b594bc6fcd
certbot==0.14.2 \
--hash=sha256:525e15e43c833db9a9934308d69dcdd220fa799488cd84543748671c68aba73d \
--hash=sha256:5bc8547dcfc0fc587e15253e264f79d8397e48bfbc8697d5aca87eae978769ac
certbot-apache==0.14.2 \
--hash=sha256:15647d424a5a7e4c44c684324ac07a457a2e0d61fce1acaa421c0b641941a350 \
--hash=sha256:e5220d3e6ee5114b41b398110dfbd8f13bd1e8c7902758634449e0b4ae515b76
certbot-nginx==0.14.2 \
--hash=sha256:231377fbdfb6303adddc73fe3f856b9fb6d0175db825650e39fe3dfd6a58f8ef \
--hash=sha256:529a18280acf41f5f7e0fe7d82c0a5d4d197d14f82742eaec54bb1d3f69c325a
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -171,15 +171,15 @@ letsencrypt==0.7.0 \
# THE LINES BELOW ARE EDITED BY THE RELEASE SCRIPT; ADD ALL DEPENDENCIES ABOVE.
acme==0.14.0 \
--hash=sha256:fca8766a2596833e8886f7ef72cf82d1f6c6cffa895781a5676861c251b24b70 \
--hash=sha256:ce7d2bca31e85adac1030c944e0a9d96e8b0f85cdc616b78d40eb09c91803543
certbot==0.14.0 \
--hash=sha256:071790b1ec4e5b94aa1688f8a62a10905c28438cd55d990cdb8c9f733d3a4a41 \
--hash=sha256:98add3721e1edaedb404879a9d39bd49020e94fc8eedbc46032a00ada51d7741
certbot-apache==0.14.0 \
--hash=sha256:ab837efce7aa4c4e47a724a60dcbeacadb9dfe64bd1d32a4e854678c4fcd82a3 \
--hash=sha256:bbcd21d9f3fd8cdc4453ef94d0cb6033c3a19f879dcd314231501ebb7180168f
certbot-nginx==0.14.0 \
--hash=sha256:608b2f6f2b04ce93c503a95ffba4f0e0ca2e0cb9ea587a8376368fa621b388e4 \
--hash=sha256:86e964b2a7818cc165d913e27e504f2ef2f60750ab0db6d39bfb3465d54c30db
acme==0.14.2 \
--hash=sha256:b3068d360beccd3b23a81d7cd2522437d847328811b573a5fe14eb04147667cf \
--hash=sha256:166b7f4858f5b144b03236b995b787a9da1e410121fb7dcac9c7d3b594bc6fcd
certbot==0.14.2 \
--hash=sha256:525e15e43c833db9a9934308d69dcdd220fa799488cd84543748671c68aba73d \
--hash=sha256:5bc8547dcfc0fc587e15253e264f79d8397e48bfbc8697d5aca87eae978769ac
certbot-apache==0.14.2 \
--hash=sha256:15647d424a5a7e4c44c684324ac07a457a2e0d61fce1acaa421c0b641941a350 \
--hash=sha256:e5220d3e6ee5114b41b398110dfbd8f13bd1e8c7902758634449e0b4ae515b76
certbot-nginx==0.14.2 \
--hash=sha256:231377fbdfb6303adddc73fe3f856b9fb6d0175db825650e39fe3dfd6a58f8ef \
--hash=sha256:529a18280acf41f5f7e0fe7d82c0a5d4d197d14f82742eaec54bb1d3f69c325a