From c06e40dbefadb95c3441af444c552926c5f6c5dd Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 26 Apr 2021 13:50:10 -0700 Subject: [PATCH 01/16] Update certbot-auto modification checks (#8805) * revert changes to letsencrypt-auto-source/le-auto * update modification tests --- .../templates/jobs/standard-tests-jobs.yml | 2 + letsencrypt-auto-source/letsencrypt-auto | 2 +- tests/modification-check.py | 152 +++++------------- tox.ini | 5 +- 4 files changed, 48 insertions(+), 113 deletions(-) diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index 62f22b223..c949af44a 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -56,6 +56,8 @@ jobs: apache-compat: IMAGE_NAME: ubuntu-18.04 TOXENV: apache_compat + # le-modification can be moved to the extended test suite once + # https://github.com/certbot/certbot/issues/8742 is resolved. le-modification: IMAGE_NAME: ubuntu-18.04 TOXENV: modification diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 9ddc7e076..c37c45596 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.15.0.dev0" +LE_AUTO_VERSION="1.14.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates diff --git a/tests/modification-check.py b/tests/modification-check.py index 357b25350..8f3ae1264 100755 --- a/tests/modification-check.py +++ b/tests/modification-check.py @@ -1,122 +1,58 @@ #!/usr/bin/env python +"""Ensures there have been no changes to important certbot-auto files.""" -from __future__ import print_function - +import hashlib import os -import shutil -import subprocess -import sys -import tempfile -from urllib.request import urlretrieve -def find_repo_path(): +# Relative to the root of the Certbot repo, these files are expected to exist +# and have the SHA-256 hashes contained in this dictionary. These hashes were +# taken from our v1.14.0 tag which was the last release we intended to make +# changes to certbot-auto. +# +# certbot-auto, letsencrypt-auto, and letsencrypt-auto-source/certbot-auto.asc +# can be removed from this dict after coordinating with tech ops to ensure we +# get the behavior we want from https://dl.eff.org. See +# https://github.com/certbot/certbot/issues/8742 for more info. +# +# Deleting letsencrypt-auto-source/letsencrypt-auto and +# letsencrypt-auto-source/letsencrypt-auto.sig can be done once we're +# comfortable breaking any certbot-auto scripts that haven't already updated to +# the last version. See +# https://opensource.eff.org/eff-open-source/pl/65geri7c4tr6iqunc1rpb3mpna for +# more info. +EXPECTED_FILES = { + 'certbot-auto': + 'b997e3608526650a08e36e682fc3bf0c29903c06fa5ba4cc49308c43832450c2', + 'letsencrypt-auto': + 'b997e3608526650a08e36e682fc3bf0c29903c06fa5ba4cc49308c43832450c2', + os.path.join('letsencrypt-auto-source', 'letsencrypt-auto'): + 'b997e3608526650a08e36e682fc3bf0c29903c06fa5ba4cc49308c43832450c2', + os.path.join('letsencrypt-auto-source', 'certbot-auto.asc'): + '0558ba7bd816732b38c092e8fedb6033dad01f263e290ec6b946263aaf6625a8', + os.path.join('letsencrypt-auto-source', 'letsencrypt-auto.sig'): + '61c036aabf75da350b0633da1b2bef0260303921ecda993455ea5e6d3af3b2fe', +} + + +def find_repo_root(): return os.path.dirname(os.path.dirname(os.path.realpath(__file__))) -# We do not use filecmp.cmp to take advantage of universal newlines -# handling in open() for Python 3.x and be insensitive to CRLF/LF when run on Windows. -# As a consequence, this function will not work correctly if executed by Python 2.x on Windows. -# But it will work correctly on Linux for any version, because every file tested will be LF. -def compare_files(path_1, path_2): - l1 = l2 = True - with open(path_1, 'r') as f1, open(path_2, 'r') as f2: - line = 1 - while l1 and l2: - line += 1 - l1 = f1.readline() - l2 = f2.readline() - if l1 != l2: - print('---') - print(( - 'While comparing {0} (1) and {1} (2), a difference was found at line {2}:' - .format(os.path.basename(path_1), os.path.basename(path_2), line))) - print('(1): {0}'.format(repr(l1))) - print('(2): {0}'.format(repr(l2))) - print('---') - return False - return True +def sha256_hash(filename): + hash_object = hashlib.sha256() + with open(filename, 'rb') as f: + hash_object.update(f.read()) + return hash_object.hexdigest() -def validate_scripts_content(repo_path, temp_cwd): - errors = False - - if not compare_files( - os.path.join(repo_path, 'certbot-auto'), - os.path.join(repo_path, 'letsencrypt-auto')): - print('Root certbot-auto and letsencrypt-auto differ.') - errors = True - else: - shutil.copyfile( - os.path.join(repo_path, 'certbot-auto'), - os.path.join(temp_cwd, 'local-auto')) - shutil.copy(os.path.normpath(os.path.join( - repo_path, - 'letsencrypt-auto-source/pieces/fetch.py')), temp_cwd) - - # Compare file against current version in the target branch - branch = os.environ.get('TARGET_BRANCH', 'master') - url = ( - 'https://raw.githubusercontent.com/certbot/certbot/{0}/certbot-auto' - .format(branch)) - urlretrieve(url, os.path.join(temp_cwd, 'certbot-auto')) - - if compare_files( - os.path.join(temp_cwd, 'certbot-auto'), - os.path.join(temp_cwd, 'local-auto')): - print('Root *-auto were unchanged') - else: - # Compare file against the latest released version - latest_version = subprocess.check_output( - [sys.executable, 'fetch.py', '--latest-version'], cwd=temp_cwd) - subprocess.check_call( - [sys.executable, 'fetch.py', '--le-auto-script', - 'v{0}'.format(latest_version.decode().strip())], cwd=temp_cwd) - if compare_files( - os.path.join(temp_cwd, 'letsencrypt-auto'), - os.path.join(temp_cwd, 'local-auto')): - print('Root *-auto were updated to the latest version.') - else: - print('Root *-auto have unexpected changes.') - errors = True - - return errors def main(): - repo_path = find_repo_path() - temp_cwd = tempfile.mkdtemp() - errors = False + repo_root = find_repo_root() + for filename, expected_hash in EXPECTED_FILES.items(): + filepath = os.path.join(repo_root, filename) + assert sha256_hash(filepath) == expected_hash, f'unexpected changes to {filepath}' + print('All certbot-auto files have correct hashes.') - try: - errors = validate_scripts_content(repo_path, temp_cwd) - - shutil.copyfile( - os.path.normpath(os.path.join(repo_path, 'letsencrypt-auto-source/letsencrypt-auto')), - os.path.join(temp_cwd, 'original-lea') - ) - subprocess.check_call([sys.executable, os.path.normpath(os.path.join( - repo_path, 'letsencrypt-auto-source/build.py'))]) - shutil.copyfile( - os.path.normpath(os.path.join(repo_path, 'letsencrypt-auto-source/letsencrypt-auto')), - os.path.join(temp_cwd, 'build-lea') - ) - shutil.copyfile( - os.path.join(temp_cwd, 'original-lea'), - os.path.normpath(os.path.join(repo_path, 'letsencrypt-auto-source/letsencrypt-auto')) - ) - - if not compare_files( - os.path.join(temp_cwd, 'original-lea'), - os.path.join(temp_cwd, 'build-lea')): - print('Script letsencrypt-auto-source/letsencrypt-auto ' - 'doesn\'t match output of build.py.') - errors = True - else: - print('Script letsencrypt-auto-source/letsencrypt-auto matches output of build.py.') - finally: - shutil.rmtree(temp_cwd) - - return errors if __name__ == '__main__': - if main(): - sys.exit(1) + main() diff --git a/tox.ini b/tox.ini index ada7002da..90aecc1b3 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ [tox] skipsdist = true -envlist = modification,py3-cover,lint,mypy +envlist = py3-cover,lint,mypy [base] # pip installs the requested packages in editable mode @@ -182,12 +182,9 @@ commands = {[base]pip_install} acme certbot certbot-apache certbot-nginx python certbot-compatibility-test/nginx/roundtrip.py certbot-compatibility-test/nginx/nginx-roundtrip-testdata -# This is a duplication of the command line in testenv:le_auto to -# allow users to run the modification check by running `tox` [testenv:modification] commands = python {toxinidir}/tests/modification-check.py -passenv = TARGET_BRANCH [testenv:apache_compat] commands = From ba912018f8507e190b5a90611c91201d952efdb9 Mon Sep 17 00:00:00 2001 From: ohemorange Date: Mon, 26 Apr 2021 15:18:05 -0700 Subject: [PATCH 02/16] Remove pytest run from release script (#8810) Fixes #8802. Also removed the unused `kgs` cruft while I was here, since it's leftover from the [initial release commit](https://github.com/certbot/certbot/commit/3c08b512c3b546528880a1353f6b8607307533a3) and I'm pretty sure we don't use that anymore. --- tools/_release.sh | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tools/_release.sh b/tools/_release.sh index 5166753d2..ba54536bf 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -177,23 +177,6 @@ cd ~- CERTBOT_DOCS=1 certbot --help all > certbot/docs/cli-help.txt jws --help > acme/docs/jws-help.txt -cd .. -# freeze before installing anything else, so that we know end-user KGS -# make sure "twine upload" doesn't catch "kgs" -if [ -d kgs ] ; then - echo Deleting old kgs... - rm -rf kgs -fi -mkdir kgs -kgs="kgs/$version" -pip freeze | tee $kgs -python ../tools/pip_install.py pytest -cd ~- -for module in $SUBPKGS ; do - echo testing $module - # use an empty configuration file rather than the one in the repo root - pytest -c <(echo '') $module -done deactivate From ac3edc2c1d4ca1098a7d6517f12688e378f965b3 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 26 Apr 2021 15:47:49 -0700 Subject: [PATCH 03/16] don't ignore kgs (#8811) --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 34b3fc99e..f4542f412 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ build/ dist*/ /venv*/ -/kgs/ /.tox/ /releases*/ /log* From f339d23e54e88e7568251e9436281506b19ac86f Mon Sep 17 00:00:00 2001 From: ohemorange Date: Tue, 27 Apr 2021 15:27:21 -0700 Subject: [PATCH 04/16] Remove further references to certbot-auto in the repo (#8814) * Move version.py to tests/letstest since it's used by test_sdists.sh * Delete unused components of certbot-auto * Remove test_leauto_upgrades.sh and references to it * Remove test_letsencrypt_auto_certonly_standalone.sh and references to it * Remove outstanding references to certbot-auto * Remove references to letsencrypt-auto * find certbot in the correct directory * delete letsencrypt-auto-source line from .isort.cfg since that directory no longer contains any python code * remove (-auto) from certbot(-auto) * delete line from test * Improve style for version.py --- .../templates/jobs/extended-tests-jobs.yml | 6 - .gitignore | 1 - .isort.cfg | 1 - certbot/certbot/_internal/cli/__init__.py | 3 +- certbot/certbot/_internal/client.py | 2 +- certbot/tests/client_test.py | 1 - letsencrypt-auto-source/build.py | 54 -- .../letsencrypt-auto.template | 786 ------------------ .../pieces/bootstrappers/arch_common.sh | 37 - .../pieces/bootstrappers/deb_common.sh | 67 -- .../pieces/bootstrappers/free_bsd.sh | 15 - .../pieces/bootstrappers/gentoo_common.sh | 31 - .../pieces/bootstrappers/mac.sh | 48 -- .../pieces/bootstrappers/mageia_common.sh | 30 - .../pieces/bootstrappers/rpm_common.sh | 45 - .../pieces/bootstrappers/rpm_common_base.sh | 60 -- .../pieces/bootstrappers/rpm_python3.sh | 23 - .../bootstrappers/rpm_python3_legacy.sh | 78 -- .../pieces/bootstrappers/smartos.sh | 8 - .../pieces/bootstrappers/suse_common.sh | 36 - .../pieces/certbot-requirements.txt | 12 - .../pieces/check_permissions.py | 81 -- letsencrypt-auto-source/pieces/create_venv.py | 27 - .../pieces/dependency-requirements.txt | 264 ------ letsencrypt-auto-source/pieces/fetch.py | 148 ---- .../pieces/letsencrypt-requirements.txt | 10 - letsencrypt-auto-source/pieces/pipstrap.py | 182 ---- letsencrypt-auto-source/tests/signing.key | 27 - tests/letstest/README.md | 3 +- tests/letstest/multitester.py | 4 +- .../letstest/scripts/test_leauto_upgrades.sh | 160 ---- ...st_letsencrypt_auto_certonly_standalone.sh | 29 - tests/letstest/scripts/test_sdists.sh | 2 +- .../letstest/scripts}/version.py | 7 +- tox.ini | 14 - 35 files changed, 9 insertions(+), 2293 deletions(-) delete mode 100755 letsencrypt-auto-source/build.py delete mode 100755 letsencrypt-auto-source/letsencrypt-auto.template delete mode 100755 letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh delete mode 100644 letsencrypt-auto-source/pieces/bootstrappers/deb_common.sh delete mode 100755 letsencrypt-auto-source/pieces/bootstrappers/free_bsd.sh delete mode 100755 letsencrypt-auto-source/pieces/bootstrappers/gentoo_common.sh delete mode 100755 letsencrypt-auto-source/pieces/bootstrappers/mac.sh delete mode 100644 letsencrypt-auto-source/pieces/bootstrappers/mageia_common.sh delete mode 100755 letsencrypt-auto-source/pieces/bootstrappers/rpm_common.sh delete mode 100644 letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh delete mode 100644 letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh delete mode 100644 letsencrypt-auto-source/pieces/bootstrappers/rpm_python3_legacy.sh delete mode 100644 letsencrypt-auto-source/pieces/bootstrappers/smartos.sh delete mode 100755 letsencrypt-auto-source/pieces/bootstrappers/suse_common.sh delete mode 100644 letsencrypt-auto-source/pieces/certbot-requirements.txt delete mode 100644 letsencrypt-auto-source/pieces/check_permissions.py delete mode 100755 letsencrypt-auto-source/pieces/create_venv.py delete mode 100644 letsencrypt-auto-source/pieces/dependency-requirements.txt delete mode 100644 letsencrypt-auto-source/pieces/fetch.py delete mode 100644 letsencrypt-auto-source/pieces/letsencrypt-requirements.txt delete mode 100755 letsencrypt-auto-source/pieces/pipstrap.py delete mode 100644 letsencrypt-auto-source/tests/signing.key delete mode 100755 tests/letstest/scripts/test_leauto_upgrades.sh delete mode 100755 tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh rename {letsencrypt-auto-source => tests/letstest/scripts}/version.py (75%) diff --git a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml index cffedfcb2..c8cbe7fb3 100644 --- a/.azure-pipelines/templates/jobs/extended-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/extended-tests-jobs.yml @@ -85,12 +85,6 @@ jobs: IMAGE_NAME: macOS-10.15 PYTHON_VERSION: 3.8 TOXENV: test-farm-apache2 - farmtest-leauto-upgrades: - PYTHON_VERSION: 3.7 - TOXENV: test-farm-leauto-upgrades - farmtest-certonly-standalone: - PYTHON_VERSION: 3.7 - TOXENV: test-farm-certonly-standalone farmtest-sdists: PYTHON_VERSION: 3.7 TOXENV: test-farm-sdists diff --git a/.gitignore b/.gitignore index f4542f412..a50dddc06 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ dist*/ /log* letsencrypt.log certbot.log -letsencrypt-auto-source/letsencrypt-auto.sig.lzma.base64 poetry.lock # coverage diff --git a/.isort.cfg b/.isort.cfg index 11c895f4d..6b17b459b 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,6 +1,5 @@ [settings] skip_glob=venv* -skip=letsencrypt-auto-source force_sort_within_sections=True force_single_line=True order_by_type=False diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py index d835d0f13..7d53ad649 100644 --- a/certbot/certbot/_internal/cli/__init__.py +++ b/certbot/certbot/_internal/cli/__init__.py @@ -243,8 +243,7 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): " to --server " + constants.STAGING_URI) helpful.add( "testing", "--debug", action="store_true", default=flag_default("debug"), - help="Show tracebacks in case of errors, and allow certbot-auto " - "execution on experimental platforms") + help="Show tracebacks in case of errors") helpful.add( [None, "certonly", "run"], "--debug-challenges", action="store_true", default=flag_default("debug_challenges"), diff --git a/certbot/certbot/_internal/client.py b/certbot/certbot/_internal/client.py index 0442febda..b5ee73211 100644 --- a/certbot/certbot/_internal/client.py +++ b/certbot/certbot/_internal/client.py @@ -58,7 +58,7 @@ def determine_user_agent(config): ua = ("CertbotACMEClient/{0} ({1}; {2}{8}) Authenticator/{3} Installer/{4} " "({5}; flags: {6}) Py/{7}") if os.environ.get("CERTBOT_DOCS") == "1": - cli_command = "certbot(-auto)" + cli_command = "certbot" os_info = "OS_NAME OS_VERSION" python_version = "major.minor.patchlevel" else: diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 2acaa71b1..1d88ea84c 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -47,7 +47,6 @@ class DetermineUserAgentTest(test_util.ConfigTestCase): doc_value_check = self.assertNotIn real_value_check = self.assertIn - doc_value_check("certbot(-auto)", ua) doc_value_check("OS_NAME OS_VERSION", ua) doc_value_check("major.minor.patchlevel", ua) real_value_check(util.get_os_info_ua(), ua) diff --git a/letsencrypt-auto-source/build.py b/letsencrypt-auto-source/build.py deleted file mode 100755 index a1e40fe44..000000000 --- a/letsencrypt-auto-source/build.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -"""Stitch together the letsencrypt-auto script. - -Implement a simple templating language in which {{ some/file }} turns into the -contents of the file at ./pieces/some/file except for certain tokens which have -other, special definitions. - -""" -from os.path import abspath, dirname, join -import re - -from version import certbot_version, file_contents - - -DIR = dirname(abspath(__file__)) - - -def build(version=None, requirements=None): - """Return the built contents of the letsencrypt-auto script. - - :arg version: The version to attach to the script. Default: the version of - the certbot package - :arg requirements: The contents of the requirements file to embed. Default: - contents of dependency-requirements.txt, letsencrypt-requirements.txt, - and certbot-requirements.txt - - """ - special_replacements = { - 'LE_AUTO_VERSION': version or certbot_version(DIR) - } - if requirements: - special_replacements['dependency-requirements.txt'] = '' - special_replacements['letsencrypt-requirements.txt'] = '' - special_replacements['certbot-requirements.txt'] = requirements - - def replacer(match): - token = match.group(1) - if token in special_replacements: - return special_replacements[token] - else: - return file_contents(join(DIR, 'pieces', token)) - - return re.sub(r'{{\s*([A-Za-z0-9_./-]+)\s*}}', - replacer, - file_contents(join(DIR, 'letsencrypt-auto.template'))) - - -def main(): - with open(join(DIR, 'letsencrypt-auto'), 'w') as out: - out.write(build()) - - -if __name__ == '__main__': - main() diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template deleted file mode 100755 index 72876bb59..000000000 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ /dev/null @@ -1,786 +0,0 @@ -#!/bin/sh -# -# Download and run the latest release version of the Certbot client. -# -# NOTE: THIS SCRIPT IS AUTO-GENERATED AND SELF-UPDATING -# -# IF YOU WANT TO EDIT IT LOCALLY, *ALWAYS* RUN YOUR COPY WITH THE -# "--no-self-upgrade" FLAG -# -# IF YOU WANT TO SEND PULL REQUESTS, THE REAL SOURCE FOR THIS FILE IS -# letsencrypt-auto-source/letsencrypt-auto.template AND -# letsencrypt-auto-source/pieces/bootstrappers/* - -set -e # Work even if somebody does "sh thisscript.sh". - -# Note: you can set XDG_DATA_HOME or VENV_PATH before running this script, -# if you want to change where the virtual environment will be installed - -# HOME might not be defined when being run through something like systemd -if [ -z "$HOME" ]; then - HOME=~root -fi -if [ -z "$XDG_DATA_HOME" ]; then - XDG_DATA_HOME=~/.local/share -fi -if [ -z "$VENV_PATH" ]; then - # We export these values so they are preserved properly if this script is - # rerun with sudo/su where $HOME/$XDG_DATA_HOME may have a different value. - export OLD_VENV_PATH="$XDG_DATA_HOME/letsencrypt" - export VENV_PATH="/opt/eff.org/certbot/venv" -fi -VENV_BIN="$VENV_PATH/bin" -BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="{{ LE_AUTO_VERSION }}" -BASENAME=$(basename $0) -USAGE="Usage: $BASENAME [OPTIONS] -A self-updating wrapper script for the Certbot ACME client. When run, updates -to both this script and certbot will be downloaded and installed. After -ensuring you have the latest versions installed, certbot will be invoked with -all arguments you have provided. - -Help for certbot itself cannot be provided until it is installed. - - --debug attempt experimental installation - -h, --help print this help - -n, --non-interactive, --noninteractive run without asking for user input - --no-bootstrap do not install OS dependencies - --no-permissions-check do not warn about file system permissions - --no-self-upgrade do not download updates - --os-packages-only install OS dependencies and exit - --install-only install certbot, upgrade if needed, and exit - -v, --verbose provide more output - -q, --quiet provide only update/error output; - implies --non-interactive - -All arguments are accepted and forwarded to the Certbot client when run." -export CERTBOT_AUTO="$0" - -for arg in "$@" ; do - case "$arg" in - --debug) - DEBUG=1;; - --os-packages-only) - OS_PACKAGES_ONLY=1;; - --install-only) - INSTALL_ONLY=1;; - --no-self-upgrade) - # Do not upgrade this script (also prevents client upgrades, because each - # copy of the script pins a hash of the python client) - NO_SELF_UPGRADE=1;; - --no-permissions-check) - NO_PERMISSIONS_CHECK=1;; - --no-bootstrap) - NO_BOOTSTRAP=1;; - --help) - HELP=1;; - --noninteractive|--non-interactive) - NONINTERACTIVE=1;; - --quiet) - QUIET=1;; - renew) - ASSUME_YES=1;; - --verbose) - VERBOSE=1;; - -[!-]*) - OPTIND=1 - while getopts ":hnvq" short_arg $arg; do - case "$short_arg" in - h) - HELP=1;; - n) - NONINTERACTIVE=1;; - q) - QUIET=1;; - v) - VERBOSE=1;; - esac - done;; - esac -done - -if [ $BASENAME = "letsencrypt-auto" ]; then - # letsencrypt-auto does not respect --help or --yes for backwards compatibility - NONINTERACTIVE=1 - HELP=0 -fi - -# Set ASSUME_YES to 1 if QUIET or NONINTERACTIVE -if [ "$QUIET" = 1 -o "$NONINTERACTIVE" = 1 ]; then - ASSUME_YES=1 -fi - -say() { - if [ "$QUIET" != 1 ]; then - echo "$@" - fi -} - -error() { - echo "$@" -} - -# Support for busybox and others where there is no "command", -# but "which" instead -if command -v command > /dev/null 2>&1 ; then - export EXISTS="command -v" -elif which which > /dev/null 2>&1 ; then - export EXISTS="which" -else - error "Cannot find command nor which... please install one!" - exit 1 -fi - -# Certbot itself needs root access for almost all modes of operation. -# certbot-auto needs root access to bootstrap OS dependencies and install -# Certbot at a protected path so it can be safely run as root. To accomplish -# this, this script will attempt to run itself as root if it doesn't have the -# necessary privileges by using `sudo` or falling back to `su` if it is not -# available. The mechanism used to obtain root access can be set explicitly by -# setting the environment variable LE_AUTO_SUDO to 'sudo', 'su', 'su_sudo', -# 'SuSudo', or '' as used below. - -# Because the parameters in `su -c` has to be a string, -# we need to properly escape it. -SuSudo() { - args="" - # This `while` loop iterates over all parameters given to this function. - # For each parameter, all `'` will be replace by `'"'"'`, and the escaped string - # will be wrapped in a pair of `'`, then appended to `$args` string - # For example, `echo "It's only 1\$\!"` will be escaped to: - # 'echo' 'It'"'"'s only 1$!' - # │ │└┼┘│ - # │ │ │ └── `'s only 1$!'` the literal string - # │ │ └── `\"'\"` is a single quote (as a string) - # │ └── `'It'`, to be concatenated with the strings following it - # └── `echo` wrapped in a pair of `'`, it's totally fine for the shell command itself - while [ $# -ne 0 ]; do - args="$args'$(printf "%s" "$1" | sed -e "s/'/'\"'\"'/g")' " - shift - done - su root -c "$args" -} - -# Sets the environment variable SUDO to be the name of the program or function -# to call to get root access. If this script already has root privleges, SUDO -# is set to an empty string. The value in SUDO should be run with the command -# to called with root privileges as arguments. -SetRootAuthMechanism() { - SUDO="" - if [ -n "${LE_AUTO_SUDO+x}" ]; then - case "$LE_AUTO_SUDO" in - SuSudo|su_sudo|su) - SUDO=SuSudo - ;; - sudo) - SUDO="sudo -E" - ;; - '') - # If we're not running with root, don't check that this script can only - # be modified by system users and groups. - NO_PERMISSIONS_CHECK=1 - ;; - *) - error "Error: unknown root authorization mechanism '$LE_AUTO_SUDO'." - exit 1 - esac - say "Using preset root authorization mechanism '$LE_AUTO_SUDO'." - else - if test "`id -u`" -ne "0" ; then - if $EXISTS sudo 1>/dev/null 2>&1; then - SUDO="sudo -E" - else - say \"sudo\" is not available, will use \"su\" for installation steps... - SUDO=SuSudo - fi - fi - fi -} - -if [ "$1" = "--cb-auto-has-root" ]; then - shift 1 -else - SetRootAuthMechanism - if [ -n "$SUDO" ]; then - say "Requesting to rerun $0 with root privileges..." - $SUDO "$0" --cb-auto-has-root "$@" - exit 0 - fi -fi - -# Runs this script again with the given arguments. --cb-auto-has-root is added -# to the command line arguments to ensure we don't try to acquire root a -# second time. After the script is rerun, we exit the current script. -RerunWithArgs() { - "$0" --cb-auto-has-root "$@" - exit 0 -} - -BootstrapMessage() { - # Arguments: Platform name - say "Bootstrapping dependencies for $1... (you can skip this with --no-bootstrap)" -} - -ExperimentalBootstrap() { - # Arguments: Platform name, bootstrap function name - if [ "$DEBUG" = 1 ]; then - if [ "$2" != "" ]; then - BootstrapMessage $1 - $2 - fi - else - error "FATAL: $1 support is very experimental at present..." - error "if you would like to work on improving it, please ensure you have backups" - error "and then run this script again with the --debug flag!" - error "Alternatively, you can install OS dependencies yourself and run this script" - error "again with --no-bootstrap." - exit 1 - fi -} - -DeprecationBootstrap() { - # Arguments: Platform name, bootstrap function name - if [ "$DEBUG" = 1 ]; then - if [ "$2" != "" ]; then - BootstrapMessage $1 - $2 - fi - else - error "WARNING: certbot-auto support for this $1 is DEPRECATED!" - error "Please visit certbot.eff.org to learn how to download a version of" - error "Certbot that is packaged for your system. While an existing version" - error "of certbot-auto may work currently, we have stopped supporting updating" - error "system packages for your system. Please switch to a packaged version" - error "as soon as possible." - exit 1 - fi -} - -MIN_PYTHON_2_VERSION="2.7" -MIN_PYVER2=$(echo "$MIN_PYTHON_2_VERSION" | sed 's/\.//') -MIN_PYTHON_3_VERSION="3.6" -MIN_PYVER3=$(echo "$MIN_PYTHON_3_VERSION" | sed 's/\.//') -# Sets LE_PYTHON to Python version string and PYVER to the first two -# digits of the python version. -# MIN_PYVER and MIN_PYTHON_VERSION are also set by this function, and their -# values depend on if we try to use Python 3 or Python 2. -DeterminePythonVersion() { - # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python - # - # If no Python is found, PYVER is set to 0. - if [ "$USE_PYTHON_3" = 1 ]; then - MIN_PYVER=$MIN_PYVER3 - MIN_PYTHON_VERSION=$MIN_PYTHON_3_VERSION - for LE_PYTHON in "$LE_PYTHON" python3; do - # Break (while keeping the LE_PYTHON value) if found. - $EXISTS "$LE_PYTHON" > /dev/null && break - done - else - MIN_PYVER=$MIN_PYVER2 - MIN_PYTHON_VERSION=$MIN_PYTHON_2_VERSION - for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do - # Break (while keeping the LE_PYTHON value) if found. - $EXISTS "$LE_PYTHON" > /dev/null && break - done - fi - if [ "$?" != "0" ]; then - if [ "$1" != "NOCRASH" ]; then - error "Cannot find any Pythons; please install one!" - exit 1 - else - PYVER=0 - return 0 - fi - fi - - PYVER=$("$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//') - if [ "$PYVER" -lt "$MIN_PYVER" ]; then - if [ "$1" != "NOCRASH" ]; then - error "You have an ancient version of Python entombed in your operating system..." - error "This isn't going to work; you'll need at least version $MIN_PYTHON_VERSION." - exit 1 - fi - fi -} - -{{ bootstrappers/deb_common.sh }} -{{ bootstrappers/rpm_common_base.sh }} -{{ bootstrappers/rpm_common.sh }} -{{ bootstrappers/rpm_python3_legacy.sh }} -{{ bootstrappers/rpm_python3.sh }} -{{ bootstrappers/suse_common.sh }} -{{ bootstrappers/arch_common.sh }} -{{ bootstrappers/gentoo_common.sh }} -{{ bootstrappers/free_bsd.sh }} -{{ bootstrappers/mac.sh }} -{{ bootstrappers/smartos.sh }} -{{ bootstrappers/mageia_common.sh }} - -# Set Bootstrap to the function that installs OS dependencies on this system -# and BOOTSTRAP_VERSION to the unique identifier for the current version of -# that function. If Bootstrap is set to a function that doesn't install any -# packages BOOTSTRAP_VERSION is not set. -if [ -f /etc/debian_version ]; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif [ -f /etc/mageia-release ]; then - # Mageia has both /etc/mageia-release and /etc/redhat-release - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif [ -f /etc/redhat-release ]; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 - # Run DeterminePythonVersion to decide on the basis of available Python versions - # whether to use 2.x or 3.x on RedHat-like systems. - # Then, revert LE_PYTHON to its previous state. - prev_le_python="$LE_PYTHON" - unset LE_PYTHON - DeterminePythonVersion "NOCRASH" - - RPM_DIST_NAME=`(. /etc/os-release 2> /dev/null && echo $ID) || echo "unknown"` - - if [ "$PYVER" -eq 26 -a $(uname -m) != 'x86_64' ]; then - # 32 bits CentOS 6 and affiliates are not supported anymore by certbot-auto. - DEPRECATED_OS=1 - fi - - # Set RPM_DIST_VERSION to VERSION_ID from /etc/os-release after splitting on - # '.' characters (e.g. "8.0" becomes "8"). If the command exits with an - # error, RPM_DIST_VERSION is set to "unknown". - RPM_DIST_VERSION=$( (. /etc/os-release 2> /dev/null && echo "$VERSION_ID") | cut -d '.' -f1 || echo "unknown") - - # If RPM_DIST_VERSION is an empty string or it contains any nonnumeric - # characters, the value is unexpected so we set RPM_DIST_VERSION to 0. - if [ -z "$RPM_DIST_VERSION" ] || [ -n "$(echo "$RPM_DIST_VERSION" | tr -d '[0-9]')" ]; then - RPM_DIST_VERSION=0 - fi - - # Handle legacy RPM distributions - if [ "$PYVER" -eq 26 ]; then - # Check if an automated bootstrap can be achieved on this system. - if ! Python36SclIsAvailable; then - INTERACTIVE_BOOTSTRAP=1 - fi - - USE_PYTHON_3=1 - - # Try now to enable SCL rh-python36 for systems already bootstrapped - # NB: EnablePython36SCL has been defined along with BootstrapRpmPython3Legacy in certbot-auto - EnablePython36SCL - else - # Starting to Fedora 29, python2 is on a deprecation path. Let's move to python3 then. - # RHEL 8 also uses python3 by default. - if [ "$RPM_DIST_NAME" = "fedora" -a "$RPM_DIST_VERSION" -ge 29 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then - RPM_USE_PYTHON_3=1 - else - RPM_USE_PYTHON_3=0 - fi - - if [ "$RPM_USE_PYTHON_3" = 1 ]; then - USE_PYTHON_3=1 - fi - fi - - LE_PYTHON="$prev_le_python" -elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif [ -f /etc/arch-release ]; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif [ -f /etc/manjaro-release ]; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif [ -f /etc/gentoo-release ]; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif uname | grep -iq FreeBSD ; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif uname | grep -iq Darwin ; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -else - DEPRECATED_OS=1 - NO_SELF_UPGRADE=1 -fi - -# We handle this case after determining the normal bootstrap version to allow -# variables like USE_PYTHON_3 to be properly set. As described above, if the -# Bootstrap function doesn't install any packages, BOOTSTRAP_VERSION should not -# be set so we unset it here. -if [ "$NO_BOOTSTRAP" = 1 ]; then - Bootstrap() { - : - } - unset BOOTSTRAP_VERSION -fi - -if [ "$DEPRECATED_OS" = 1 ]; then - Bootstrap() { - error "Skipping bootstrap because certbot-auto is deprecated on this system." - } - unset BOOTSTRAP_VERSION -fi - -# Sets PREV_BOOTSTRAP_VERSION to the identifier for the bootstrap script used -# to install OS dependencies on this system. PREV_BOOTSTRAP_VERSION isn't set -# if it is unknown how OS dependencies were installed on this system. -SetPrevBootstrapVersion() { - if [ -f $BOOTSTRAP_VERSION_PATH ]; then - PREV_BOOTSTRAP_VERSION=$(cat "$BOOTSTRAP_VERSION_PATH") - # The list below only contains bootstrap version strings that existed before - # we started writing them to disk. - # - # DO NOT MODIFY THIS LIST UNLESS YOU KNOW WHAT YOU'RE DOING! - elif grep -Fqx "$BOOTSTRAP_VERSION" << "UNLIKELY_EOF" -BootstrapDebCommon 1 -BootstrapMageiaCommon 1 -BootstrapRpmCommon 1 -BootstrapSuseCommon 1 -BootstrapArchCommon 1 -BootstrapGentooCommon 1 -BootstrapFreeBsd 1 -BootstrapMac 1 -BootstrapSmartOS 1 -UNLIKELY_EOF - then - # If there's no bootstrap version saved to disk, but the currently selected - # bootstrap script is from before we started saving the version number, - # return the currently selected version to prevent us from rebootstrapping - # unnecessarily. - PREV_BOOTSTRAP_VERSION="$BOOTSTRAP_VERSION" - fi -} - -TempDir() { - mktemp -d 2>/dev/null || mktemp -d -t 'le' # Linux || macOS -} - -# Returns 0 if a letsencrypt installation exists at $OLD_VENV_PATH, otherwise, -# returns a non-zero number. -OldVenvExists() { - [ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ] -} - -# Given python path, version 1 and version 2, check if version 1 is outdated compared to version 2. -# An unofficial version provided as version 1 (eg. 0.28.0.dev0) will be treated -# specifically by printing "UNOFFICIAL". Otherwise, print "OUTDATED" if version 1 -# is outdated, and "UP_TO_DATE" if not. -# This function relies only on installed python environment (2.x or 3.x) by certbot-auto. -CompareVersions() { - "$1" - "$2" "$3" << "UNLIKELY_EOF" -import sys -from distutils.version import StrictVersion - -try: - current = StrictVersion(sys.argv[1]) -except ValueError: - sys.stdout.write('UNOFFICIAL') - sys.exit() - -try: - remote = StrictVersion(sys.argv[2]) -except ValueError: - sys.stdout.write('UP_TO_DATE') - sys.exit() - -if current < remote: - sys.stdout.write('OUTDATED') -else: - sys.stdout.write('UP_TO_DATE') -UNLIKELY_EOF -} - -# Create a new virtual environment for Certbot. It will overwrite any existing one. -# Parameters: LE_PYTHON, VENV_PATH, PYVER, VERBOSE -CreateVenv() { - "$1" - "$2" "$3" "$4" << "UNLIKELY_EOF" -{{ create_venv.py }} -UNLIKELY_EOF -} - -# Check that the given PATH_TO_CHECK has secured permissions. -# Parameters: LE_PYTHON, PATH_TO_CHECK -CheckPathPermissions() { - "$1" - "$2" << "UNLIKELY_EOF" -{{ check_permissions.py }} -UNLIKELY_EOF -} - -if [ "$1" = "--le-auto-phase2" ]; then - # Phase 2: Create venv, install LE, and run. - - shift 1 # the --le-auto-phase2 arg - - if [ "$DEPRECATED_OS" = 1 ]; then - # Phase 2 damage control mode for deprecated OSes. - # In this situation, we bypass any bootstrap or certbot venv setup. - error "Your system is not supported by certbot-auto anymore." - - if [ ! -d "$VENV_PATH" ] && OldVenvExists; then - VENV_BIN="$OLD_VENV_PATH/bin" - fi - - if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then - error "certbot-auto and its Certbot installation will no longer receive updates." - error "You will not receive any bug fixes including those fixing server compatibility" - error "or security problems." - error "Please visit https://certbot.eff.org/ to check for other alternatives." - "$VENV_BIN/letsencrypt" "$@" - exit 0 - else - error "Certbot cannot be installed." - error "Please visit https://certbot.eff.org/ to check for other alternatives." - exit 1 - fi - fi - - SetPrevBootstrapVersion - - if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then - unset LE_PYTHON - fi - - INSTALLED_VERSION="none" - if [ -d "$VENV_PATH" ] || OldVenvExists; then - # If the selected Bootstrap function isn't a noop and it differs from the - # previously used version - if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then - # Check if we can rebootstrap without manual user intervention: this requires that - # certbot-auto is in non-interactive mode AND selected bootstrap does not claim to - # require a manual user intervention. - if [ "$NONINTERACTIVE" = 1 -a "$INTERACTIVE_BOOTSTRAP" != 1 ]; then - CAN_REBOOTSTRAP=1 - fi - # Check if rebootstrap can be done non-interactively and current shell is non-interactive - # (true if stdin and stdout are not attached to a terminal). - if [ \( "$CAN_REBOOTSTRAP" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then - if [ -d "$VENV_PATH" ]; then - rm -rf "$VENV_PATH" - fi - # In the case the old venv was just a symlink to the new one, - # OldVenvExists is now false because we deleted the venv at VENV_PATH. - if OldVenvExists; then - rm -rf "$OLD_VENV_PATH" - ln -s "$VENV_PATH" "$OLD_VENV_PATH" - fi - RerunWithArgs "$@" - # Otherwise bootstrap needs to be done manually by the user. - else - # If it is because bootstrapping is interactive, --non-interactive will be of no use. - if [ "$INTERACTIVE_BOOTSTRAP" = 1 ]; then - error "Skipping upgrade because new OS dependencies may need to be installed." - error "This requires manual user intervention: please run this script again manually." - # If this is because of the environment (eg. non interactive shell without - # --non-interactive flag set), help the user in that direction. - else - error "Skipping upgrade because new OS dependencies may need to be installed." - error - error "To upgrade to a newer version, please run this script again manually so you can" - error "approve changes or with --non-interactive on the command line to automatically" - error "install any required packages." - fi - # Set INSTALLED_VERSION to be the same so we don't update the venv - INSTALLED_VERSION="$LE_AUTO_VERSION" - # Continue to use OLD_VENV_PATH if the new venv doesn't exist - if [ ! -d "$VENV_PATH" ]; then - VENV_BIN="$OLD_VENV_PATH/bin" - fi - fi - elif [ -f "$VENV_BIN/letsencrypt" ]; then - # --version output ran through grep due to python-cryptography DeprecationWarnings - # grep for both certbot and letsencrypt until certbot and shim packages have been released - INSTALLED_VERSION=$("$VENV_BIN/letsencrypt" --version 2>&1 | grep "^certbot\|^letsencrypt" | cut -d " " -f 2) - if [ -z "$INSTALLED_VERSION" ]; then - error "Error: couldn't get currently installed version for $VENV_BIN/letsencrypt: " 1>&2 - "$VENV_BIN/letsencrypt" --version - exit 1 - fi - fi - fi - - if [ "$LE_AUTO_VERSION" != "$INSTALLED_VERSION" ]; then - say "Creating virtual environment..." - DeterminePythonVersion - CreateVenv "$LE_PYTHON" "$VENV_PATH" "$PYVER" "$VERBOSE" - - if [ -n "$BOOTSTRAP_VERSION" ]; then - echo "$BOOTSTRAP_VERSION" > "$BOOTSTRAP_VERSION_PATH" - elif [ -n "$PREV_BOOTSTRAP_VERSION" ]; then - echo "$PREV_BOOTSTRAP_VERSION" > "$BOOTSTRAP_VERSION_PATH" - fi - - say "Installing Python packages..." - TEMP_DIR=$(TempDir) - trap 'rm -rf "$TEMP_DIR"' EXIT - # There is no $ interpolation due to quotes on starting heredoc delimiter. - # ------------------------------------------------------------------------- - cat << "UNLIKELY_EOF" > "$TEMP_DIR/letsencrypt-auto-requirements.txt" -{{ dependency-requirements.txt }} -{{ letsencrypt-requirements.txt }} -{{ certbot-requirements.txt }} -UNLIKELY_EOF - # ------------------------------------------------------------------------- - cat << "UNLIKELY_EOF" > "$TEMP_DIR/pipstrap.py" -{{ pipstrap.py }} -UNLIKELY_EOF - # ------------------------------------------------------------------------- - # Set PATH so pipstrap upgrades the right (v)env: - PATH="$VENV_BIN:$PATH" "$VENV_BIN/python" "$TEMP_DIR/pipstrap.py" - set +e - if [ "$VERBOSE" = 1 ]; then - "$VENV_BIN/pip" install --disable-pip-version-check --no-cache-dir --require-hashes -r "$TEMP_DIR/letsencrypt-auto-requirements.txt" - else - PIP_OUT=`"$VENV_BIN/pip" install --disable-pip-version-check --no-cache-dir --require-hashes -r "$TEMP_DIR/letsencrypt-auto-requirements.txt" 2>&1` - fi - PIP_STATUS=$? - set -e - if [ "$PIP_STATUS" != 0 ]; then - # Report error. (Otherwise, be quiet.) - error "Had a problem while installing Python packages." - if [ "$VERBOSE" != 1 ]; then - error - error "pip prints the following errors: " - error "=====================================================" - error "$PIP_OUT" - error "=====================================================" - error - error "Certbot has problem setting up the virtual environment." - - if `echo $PIP_OUT | grep -q Killed` || `echo $PIP_OUT | grep -q "allocate memory"` ; then - error - error "Based on your pip output, the problem can likely be fixed by " - error "increasing the available memory." - else - error - error "We were not be able to guess the right solution from your pip " - error "output." - fi - - error - error "Consult https://certbot.eff.org/docs/install.html#problems-with-python-virtual-environment" - error "for possible solutions." - error "You may also find some support resources at https://certbot.eff.org/support/ ." - fi - rm -rf "$VENV_PATH" - exit 1 - fi - - if [ -d "$OLD_VENV_PATH" -a ! -L "$OLD_VENV_PATH" ]; then - rm -rf "$OLD_VENV_PATH" - ln -s "$VENV_PATH" "$OLD_VENV_PATH" - fi - - say "Installation succeeded." - fi - - # If you're modifying any of the code after this point in this current `if` block, you - # may need to update the "$DEPRECATED_OS" = 1 case at the beginning of phase 2 as well. - - if [ "$INSTALL_ONLY" = 1 ]; then - say "Certbot is installed." - exit 0 - fi - - "$VENV_BIN/letsencrypt" "$@" - -else - # Phase 1: Upgrade certbot-auto if necessary, then self-invoke. - # - # Each phase checks the version of only the thing it is responsible for - # upgrading. Phase 1 checks the version of the latest release of - # certbot-auto (which is always the same as that of the certbot - # package). Phase 2 checks the version of the locally installed certbot. - export PHASE_1_VERSION="$LE_AUTO_VERSION" - - if [ ! -f "$VENV_BIN/letsencrypt" ]; then - if ! OldVenvExists; then - if [ "$HELP" = 1 ]; then - echo "$USAGE" - exit 0 - fi - # If it looks like we've never bootstrapped before, bootstrap: - Bootstrap - fi - fi - if [ "$OS_PACKAGES_ONLY" = 1 ]; then - say "OS packages installed." - exit 0 - fi - - DeterminePythonVersion "NOCRASH" - # Don't warn about file permissions if the user disabled the check or we - # can't find an up-to-date Python. - if [ "$PYVER" -ge "$MIN_PYVER" -a "$NO_PERMISSIONS_CHECK" != 1 ]; then - # If the script fails for some reason, don't break certbot-auto. - set +e - # Suppress unexpected error output. - CHECK_PERM_OUT=$(CheckPathPermissions "$LE_PYTHON" "$0" 2>/dev/null) - CHECK_PERM_STATUS="$?" - set -e - # Only print output if the script ran successfully and it actually produced - # output. The latter check resolves - # https://github.com/certbot/certbot/issues/7012. - if [ "$CHECK_PERM_STATUS" = 0 -a -n "$CHECK_PERM_OUT" ]; then - error "$CHECK_PERM_OUT" - fi - fi - - if [ "$NO_SELF_UPGRADE" != 1 ]; then - TEMP_DIR=$(TempDir) - trap 'rm -rf "$TEMP_DIR"' EXIT - # --------------------------------------------------------------------------- - cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py" -{{ fetch.py }} -UNLIKELY_EOF - # --------------------------------------------------------------------------- - if [ "$PYVER" -lt "$MIN_PYVER" ]; then - error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates." - elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then - error "WARNING: unable to check for updates." - fi - - # If for any reason REMOTE_VERSION is not set, let's assume certbot-auto is up-to-date, - # and do not go into the self-upgrading process. - if [ -n "$REMOTE_VERSION" ]; then - LE_VERSION_STATE=`CompareVersions "$LE_PYTHON" "$LE_AUTO_VERSION" "$REMOTE_VERSION"` - - if [ "$LE_VERSION_STATE" = "UNOFFICIAL" ]; then - say "Unofficial certbot-auto version detected, self-upgrade is disabled: $LE_AUTO_VERSION" - elif [ "$LE_VERSION_STATE" = "OUTDATED" ]; then - say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" - - # Install new copy of certbot-auto. - # TODO: Deal with quotes in pathnames. - say "Replacing certbot-auto..." - # Clone permissions with cp. chmod and chown don't have a --reference - # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD: - cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" - cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" - # Using mv rather than cp leaves the old file descriptor pointing to the - # original copy so the shell can continue to read it unmolested. mv across - # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the - # cp is unlikely to fail if the rm doesn't. - mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" - fi # A newer version is available. - fi - fi # Self-upgrading is allowed. - - RerunWithArgs --le-auto-phase2 "$@" -fi diff --git a/letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh b/letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh deleted file mode 100755 index 3be78d3f8..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/arch_common.sh +++ /dev/null @@ -1,37 +0,0 @@ -# If new packages are installed by BootstrapArchCommon below, this version -# number must be increased. -BOOTSTRAP_ARCH_COMMON_VERSION=1 - -BootstrapArchCommon() { - # Tested with: - # - ArchLinux (x86_64) - # - # "python-virtualenv" is Python3, but "python2-virtualenv" provides - # only "virtualenv2" binary, not "virtualenv". - - deps=" - python2 - python-virtualenv - gcc - augeas - openssl - libffi - ca-certificates - pkg-config - " - - # pacman -T exits with 127 if there are missing dependencies - missing=$(pacman -T $deps) || true - - if [ "$ASSUME_YES" = 1 ]; then - noconfirm="--noconfirm" - fi - - if [ "$missing" ]; then - if [ "$QUIET" = 1 ]; then - pacman -S --needed $missing $noconfirm > /dev/null - else - pacman -S --needed $missing $noconfirm - fi - fi -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/deb_common.sh b/letsencrypt-auto-source/pieces/bootstrappers/deb_common.sh deleted file mode 100644 index 93bdc63b4..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/deb_common.sh +++ /dev/null @@ -1,67 +0,0 @@ -# If new packages are installed by BootstrapDebCommon below, this version -# number must be increased. -BOOTSTRAP_DEB_COMMON_VERSION=1 - -BootstrapDebCommon() { - # Current version tested with: - # - # - Ubuntu - # - 14.04 (x64) - # - 15.04 (x64) - # - Debian - # - 7.9 "wheezy" (x64) - # - sid (2015-10-21) (x64) - - # Past versions tested with: - # - # - Debian 8.0 "jessie" (x64) - # - Raspbian 7.8 (armhf) - - # Believed not to work: - # - # - Debian 6.0.10 "squeeze" (x64) - - if [ "$QUIET" = 1 ]; then - QUIET_FLAG='-qq' - fi - - apt-get $QUIET_FLAG update || error apt-get update hit problems but continuing anyway... - - # virtualenv binary can be found in different packages depending on - # distro version (#346) - - virtualenv= - # virtual env is known to apt and is installable - if apt-cache show virtualenv > /dev/null 2>&1 ; then - if ! LC_ALL=C apt-cache --quiet=0 show virtualenv 2>&1 | grep -q 'No packages found'; then - virtualenv="virtualenv" - fi - fi - - if apt-cache show python-virtualenv > /dev/null 2>&1; then - virtualenv="$virtualenv python-virtualenv" - fi - - augeas_pkg="libaugeas0 augeas-lenses" - - if [ "$ASSUME_YES" = 1 ]; then - YES_FLAG="-y" - fi - - apt-get install $QUIET_FLAG $YES_FLAG --no-install-recommends \ - python \ - python-dev \ - $virtualenv \ - gcc \ - $augeas_pkg \ - libssl-dev \ - openssl \ - libffi-dev \ - ca-certificates \ - - - if ! $EXISTS virtualenv > /dev/null ; then - error Failed to install a working \"virtualenv\" command, exiting - exit 1 - fi -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/free_bsd.sh b/letsencrypt-auto-source/pieces/bootstrappers/free_bsd.sh deleted file mode 100755 index a67c85619..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/free_bsd.sh +++ /dev/null @@ -1,15 +0,0 @@ -# If new packages are installed by BootstrapFreeBsd below, this version number -# must be increased. -BOOTSTRAP_FREEBSD_VERSION=1 - -BootstrapFreeBsd() { - if [ "$QUIET" = 1 ]; then - QUIET_FLAG="--quiet" - fi - - pkg install -Ay $QUIET_FLAG \ - python \ - py27-virtualenv \ - augeas \ - libffi -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/gentoo_common.sh b/letsencrypt-auto-source/pieces/bootstrappers/gentoo_common.sh deleted file mode 100755 index e2d24b5fb..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/gentoo_common.sh +++ /dev/null @@ -1,31 +0,0 @@ -# If new packages are installed by BootstrapGentooCommon below, this version -# number must be increased. -BOOTSTRAP_GENTOO_COMMON_VERSION=1 - -BootstrapGentooCommon() { - PACKAGES=" - dev-lang/python:2.7 - dev-python/virtualenv - app-admin/augeas - dev-libs/openssl - dev-libs/libffi - app-misc/ca-certificates - virtual/pkgconfig" - - ASK_OPTION="--ask" - if [ "$ASSUME_YES" = 1 ]; then - ASK_OPTION="" - fi - - case "$PACKAGE_MANAGER" in - (paludis) - cave resolve --preserve-world --keep-targets if-possible $PACKAGES -x - ;; - (pkgcore) - pmerge --noreplace --oneshot $ASK_OPTION $PACKAGES - ;; - (portage|*) - emerge --noreplace --oneshot $ASK_OPTION $PACKAGES - ;; - esac -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/mac.sh b/letsencrypt-auto-source/pieces/bootstrappers/mac.sh deleted file mode 100755 index 9e26d3389..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/mac.sh +++ /dev/null @@ -1,48 +0,0 @@ -# If new packages are installed by BootstrapMac below, this version number must -# be increased. -BOOTSTRAP_MAC_VERSION=1 - -BootstrapMac() { - if hash brew 2>/dev/null; then - say "Using Homebrew to install dependencies..." - pkgman=brew - pkgcmd="brew install" - elif hash port 2>/dev/null; then - say "Using MacPorts to install dependencies..." - pkgman=port - pkgcmd="port install" - else - say "No Homebrew/MacPorts; installing Homebrew..." - ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - pkgman=brew - pkgcmd="brew install" - fi - - $pkgcmd augeas - if [ "$(which python)" = "/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python" \ - -o "$(which python)" = "/usr/bin/python" ]; then - # We want to avoid using the system Python because it requires root to use pip. - # python.org, MacPorts or HomeBrew Python installations should all be OK. - say "Installing python..." - $pkgcmd python - fi - - # Workaround for _dlopen not finding augeas on macOS - if [ "$pkgman" = "port" ] && ! [ -e "/usr/local/lib/libaugeas.dylib" ] && [ -e "/opt/local/lib/libaugeas.dylib" ]; then - say "Applying augeas workaround" - mkdir -p /usr/local/lib/ - ln -s /opt/local/lib/libaugeas.dylib /usr/local/lib/ - fi - - if ! hash pip 2>/dev/null; then - say "pip not installed" - say "Installing pip..." - curl --silent --show-error --retry 5 https://bootstrap.pypa.io/get-pip.py | python - fi - - if ! hash virtualenv 2>/dev/null; then - say "virtualenv not installed." - say "Installing with pip..." - pip install virtualenv - fi -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/mageia_common.sh b/letsencrypt-auto-source/pieces/bootstrappers/mageia_common.sh deleted file mode 100644 index dfa5b47f3..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/mageia_common.sh +++ /dev/null @@ -1,30 +0,0 @@ -# If new packages are installed by BootstrapMageiaCommon below, this version -# number must be increased. -BOOTSTRAP_MAGEIA_COMMON_VERSION=1 - -BootstrapMageiaCommon() { - if [ "$QUIET" = 1 ]; then - QUIET_FLAG='--quiet' - fi - - if ! urpmi --force $QUIET_FLAG \ - python \ - libpython-devel \ - python-virtualenv - then - error "Could not install Python dependencies. Aborting bootstrap!" - exit 1 - fi - - if ! urpmi --force $QUIET_FLAG \ - git \ - gcc \ - python-augeas \ - libopenssl-devel \ - libffi-devel \ - rootcerts - then - error "Could not install additional dependencies. Aborting bootstrap!" - exit 1 - fi -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/rpm_common.sh b/letsencrypt-auto-source/pieces/bootstrappers/rpm_common.sh deleted file mode 100755 index 80d55a393..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/rpm_common.sh +++ /dev/null @@ -1,45 +0,0 @@ -# If new packages are installed by BootstrapRpmCommon below, this version -# number must be increased. -BOOTSTRAP_RPM_COMMON_VERSION=1 - -BootstrapRpmCommon() { - # Tested with: - # - Fedora 20, 21, 22, 23 (x64) - # - Centos 7 (x64: on DigitalOcean droplet) - # - CentOS 7 Minimal install in a Hyper-V VM - # - CentOS 6 - - InitializeRPMCommonBase - - # Most RPM distros use the "python" or "python-" naming convention. Let's try that first. - if $TOOL list python >/dev/null 2>&1; then - python_pkgs="$python - python-devel - python-virtualenv - python-tools - python-pip - " - # Fedora 26 starts to use the prefix python2 for python2 based packages. - # this elseif is theoretically for any Fedora over version 26: - elif $TOOL list python2 >/dev/null 2>&1; then - python_pkgs="$python2 - python2-libs - python2-setuptools - python2-devel - python2-virtualenv - python2-tools - python2-pip - " - # Some distros and older versions of current distros use a "python27" - # instead of the "python" or "python-" naming convention. - else - python_pkgs="$python27 - python27-devel - python27-virtualenv - python27-tools - python27-pip - " - fi - - BootstrapRpmCommonBase "$python_pkgs" -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh b/letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh deleted file mode 100644 index 2b00b199b..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/rpm_common_base.sh +++ /dev/null @@ -1,60 +0,0 @@ -# If new packages are installed by BootstrapRpmCommonBase below, version -# numbers in rpm_common.sh and rpm_python3.sh must be increased. - -# Sets TOOL to the name of the package manager -# Sets appropriate values for YES_FLAG and QUIET_FLAG based on $ASSUME_YES and $QUIET_FLAG. -# Note: this function is called both while selecting the bootstrap scripts and -# during the actual bootstrap. Some things like prompting to user can be done in the latter -# case, but not in the former one. -InitializeRPMCommonBase() { - if type dnf 2>/dev/null - then - TOOL=dnf - elif type yum 2>/dev/null - then - TOOL=yum - - else - error "Neither yum nor dnf found. Aborting bootstrap!" - exit 1 - fi - - if [ "$ASSUME_YES" = 1 ]; then - YES_FLAG="-y" - fi - if [ "$QUIET" = 1 ]; then - QUIET_FLAG='--quiet' - fi -} - -BootstrapRpmCommonBase() { - # Arguments: whitespace-delimited python packages to install - - InitializeRPMCommonBase # This call is superfluous in practice - - pkgs=" - gcc - augeas-libs - openssl - openssl-devel - libffi-devel - redhat-rpm-config - ca-certificates - " - - # Add the python packages - pkgs="$pkgs - $1 - " - - if $TOOL list installed "httpd" >/dev/null 2>&1; then - pkgs="$pkgs - mod_ssl - " - fi - - if ! $TOOL install $YES_FLAG $QUIET_FLAG $pkgs; then - error "Could not install OS dependencies. Aborting bootstrap!" - exit 1 - fi -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh b/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh deleted file mode 100644 index ac0553db5..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3.sh +++ /dev/null @@ -1,23 +0,0 @@ -# If new packages are installed by BootstrapRpmPython3 below, this version -# number must be increased. -BOOTSTRAP_RPM_PYTHON3_VERSION=1 - -BootstrapRpmPython3() { - # Tested with: - # - Fedora 29 - - InitializeRPMCommonBase - - # Fedora 29 must use python3-virtualenv - if $TOOL list python3-virtualenv >/dev/null 2>&1; then - python_pkgs="python3 - python3-virtualenv - python3-devel - " - else - error "No supported Python package available to install. Aborting bootstrap!" - exit 1 - fi - - BootstrapRpmCommonBase "$python_pkgs" -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3_legacy.sh b/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3_legacy.sh deleted file mode 100644 index febfc7a83..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/rpm_python3_legacy.sh +++ /dev/null @@ -1,78 +0,0 @@ -# If new packages are installed by BootstrapRpmPython3 below, this version -# number must be increased. -BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION=1 - -# Checks if rh-python36 can be installed. -Python36SclIsAvailable() { - InitializeRPMCommonBase >/dev/null 2>&1; - - if "${TOOL}" list rh-python36 >/dev/null 2>&1; then - return 0 - fi - if "${TOOL}" list centos-release-scl >/dev/null 2>&1; then - return 0 - fi - return 1 -} - -# Try to enable rh-python36 from SCL if it is necessary and possible. -EnablePython36SCL() { - if "$EXISTS" python3.6 > /dev/null 2> /dev/null; then - return 0 - fi - if [ ! -f /opt/rh/rh-python36/enable ]; then - return 0 - fi - set +e - if ! . /opt/rh/rh-python36/enable; then - error 'Unable to enable rh-python36!' - exit 1 - fi - set -e -} - -# This bootstrap concerns old RedHat-based distributions that do not ship by default -# with Python 2.7, but only Python 2.6. We bootstrap them by enabling SCL and installing -# Python 3.6. Some of these distributions are: CentOS/RHEL/OL/SL 6. -BootstrapRpmPython3Legacy() { - # Tested with: - # - CentOS 6 - - InitializeRPMCommonBase - - if ! "${TOOL}" list rh-python36 >/dev/null 2>&1; then - echo "To use Certbot on this operating system, packages from the SCL repository need to be installed." - if ! "${TOOL}" list centos-release-scl >/dev/null 2>&1; then - error "Enable the SCL repository and try running Certbot again." - exit 1 - fi - if [ "${ASSUME_YES}" = 1 ]; then - /bin/echo -n "Enabling the SCL repository in 3 seconds... (Press Ctrl-C to cancel)" - sleep 1s - /bin/echo -ne "\e[0K\rEnabling the SCL repository in 2 seconds... (Press Ctrl-C to cancel)" - sleep 1s - /bin/echo -e "\e[0K\rEnabling the SCL repository in 1 second... (Press Ctrl-C to cancel)" - sleep 1s - fi - if ! "${TOOL}" install "${YES_FLAG}" "${QUIET_FLAG}" centos-release-scl; then - error "Could not enable SCL. Aborting bootstrap!" - exit 1 - fi - fi - - # CentOS 6 must use rh-python36 from SCL - if "${TOOL}" list rh-python36 >/dev/null 2>&1; then - python_pkgs="rh-python36-python - rh-python36-python-virtualenv - rh-python36-python-devel - " - else - error "No supported Python package available to install. Aborting bootstrap!" - exit 1 - fi - - BootstrapRpmCommonBase "${python_pkgs}" - - # Enable SCL rh-python36 after bootstrapping. - EnablePython36SCL -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/smartos.sh b/letsencrypt-auto-source/pieces/bootstrappers/smartos.sh deleted file mode 100644 index ac7c0ed4a..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/smartos.sh +++ /dev/null @@ -1,8 +0,0 @@ -# If new packages are installed by BootstrapSmartOS below, this version number -# must be increased. -BOOTSTRAP_SMARTOS_VERSION=1 - -BootstrapSmartOS() { - pkgin update - pkgin -y install 'gcc49' 'py27-augeas' 'py27-virtualenv' -} diff --git a/letsencrypt-auto-source/pieces/bootstrappers/suse_common.sh b/letsencrypt-auto-source/pieces/bootstrappers/suse_common.sh deleted file mode 100755 index 7fa28ce50..000000000 --- a/letsencrypt-auto-source/pieces/bootstrappers/suse_common.sh +++ /dev/null @@ -1,36 +0,0 @@ -# If new packages are installed by BootstrapSuseCommon below, this version -# number must be increased. -BOOTSTRAP_SUSE_COMMON_VERSION=1 - -BootstrapSuseCommon() { - # SLE12 don't have python-virtualenv - - if [ "$ASSUME_YES" = 1 ]; then - zypper_flags="-nq" - install_flags="-l" - fi - - if [ "$QUIET" = 1 ]; then - QUIET_FLAG='-qq' - fi - - if zypper search -x python-virtualenv >/dev/null 2>&1; then - OPENSUSE_VIRTUALENV_PACKAGES="python-virtualenv" - else - # Since Leap 15.0 (and associated Tumbleweed version), python-virtualenv - # is a source package, and python2-virtualenv must be used instead. - # Also currently python2-setuptools is not a dependency of python2-virtualenv, - # while it should be. Installing it explicitly until upstream fix. - OPENSUSE_VIRTUALENV_PACKAGES="python2-virtualenv python2-setuptools" - fi - - zypper $QUIET_FLAG $zypper_flags in $install_flags \ - python \ - python-devel \ - $OPENSUSE_VIRTUALENV_PACKAGES \ - gcc \ - augeas-lenses \ - libopenssl-devel \ - libffi-devel \ - ca-certificates -} diff --git a/letsencrypt-auto-source/pieces/certbot-requirements.txt b/letsencrypt-auto-source/pieces/certbot-requirements.txt deleted file mode 100644 index 90c67663b..000000000 --- a/letsencrypt-auto-source/pieces/certbot-requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -certbot==1.14.0 \ - --hash=sha256:67b4d26ceaea6c7f8325d0d45169e7a165a2cabc7122c84bc971ba068ca19cca \ - --hash=sha256:959ea90c6bb8dca38eab9772722cb940972ef6afcd5f15deef08b3c3636841eb -acme==1.14.0 \ - --hash=sha256:4f48c41261202f1a389ec2986b2580b58f53e0d5a1ae2463b34318d78b87fc66 \ - --hash=sha256:61daccfb0343628cbbca551a7fc4c82482113952c21db3fe0c585b7c98fa1c35 -certbot-apache==1.14.0 \ - --hash=sha256:b757038db23db707c44630fecb46e99172bd791f0db5a8e623c0842613c4d3d9 \ - --hash=sha256:887fe4a21af2de1e5c2c9428bacba6eb7c1219257bc70f1a1d8447c8a321adb0 -certbot-nginx==1.14.0 \ - --hash=sha256:8916a815437988d6c192df9f035bb7a176eab20eee0956677b335d0698d243fb \ - --hash=sha256:cc2a8a0de56d9bb6b2efbda6c80c647dad8db2bb90675cac03ade94bd5fc8597 diff --git a/letsencrypt-auto-source/pieces/check_permissions.py b/letsencrypt-auto-source/pieces/check_permissions.py deleted file mode 100644 index ba55e6d97..000000000 --- a/letsencrypt-auto-source/pieces/check_permissions.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Verifies certbot-auto cannot be modified by unprivileged users. - -This script takes the path to certbot-auto as its only command line -argument. It then checks that the file can only be modified by uid/gid -< 1000 and if other users can modify the file, it prints a warning with -a suggestion on how to solve the problem. - -Permissions on symlinks in the absolute path of certbot-auto are ignored -and only the canonical path to certbot-auto is checked. There could be -permissions problems due to the symlinks that are unreported by this -script, however, issues like this were not caused by our documentation -and are ignored for the sake of simplicity. - -All warnings are printed to stdout rather than stderr so all stderr -output from this script can be suppressed to avoid printing messages if -this script fails for some reason. - -""" -from __future__ import print_function - -import os -import stat -import sys - - -FORUM_POST_URL = 'https://community.letsencrypt.org/t/certbot-auto-deployment-best-practices/91979/' - - -def has_safe_permissions(path): - """Returns True if the given path has secure permissions. - - The permissions are considered safe if the file is only writable by - uid/gid < 1000. - - The reason we allow more IDs than 0 is because on some systems such - as Debian, system users/groups other than uid/gid 0 are used for the - path we recommend in our instructions which is /usr/local/bin. 1000 - was chosen because on Debian 0-999 is reserved for system IDs[1] and - on RHEL either 0-499 or 0-999 is reserved depending on the - version[2][3]. Due to these differences across different OSes, this - detection isn't perfect so we only determine permissions are - insecure when we can be reasonably confident there is a problem - regardless of the underlying OS. - - [1] https://www.debian.org/doc/debian-policy/ch-opersys.html#uid-and-gid-classes - [2] https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/ch-managing_users_and_groups - [3] https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/ch-managing_users_and_groups - - :param str path: filesystem path to check - :returns: True if the path has secure permissions, otherwise, False - :rtype: bool - - """ - # os.stat follows symlinks before obtaining information about a file. - stat_result = os.stat(path) - if stat_result.st_mode & stat.S_IWOTH: - return False - if stat_result.st_mode & stat.S_IWGRP and stat_result.st_gid >= 1000: - return False - if stat_result.st_mode & stat.S_IWUSR and stat_result.st_uid >= 1000: - return False - return True - - -def main(certbot_auto_path): - current_path = os.path.realpath(certbot_auto_path) - last_path = None - permissions_ok = True - # This loop makes use of the fact that os.path.dirname('/') == '/'. - while current_path != last_path and permissions_ok: - permissions_ok = has_safe_permissions(current_path) - last_path = current_path - current_path = os.path.dirname(current_path) - - if not permissions_ok: - print('{0} has insecure permissions!'.format(certbot_auto_path)) - print('To learn how to fix them, visit {0}'.format(FORUM_POST_URL)) - - -if __name__ == '__main__': - main(sys.argv[1]) diff --git a/letsencrypt-auto-source/pieces/create_venv.py b/letsencrypt-auto-source/pieces/create_venv.py deleted file mode 100755 index a618e228a..000000000 --- a/letsencrypt-auto-source/pieces/create_venv.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -import os -import shutil -import subprocess -import sys - - -def create_venv(venv_path, pyver, verbose): - if os.path.exists(venv_path): - shutil.rmtree(venv_path) - - stdout = sys.stdout if verbose == '1' else open(os.devnull, 'w') - - if int(pyver) <= 27: - # Use virtualenv binary - environ = os.environ.copy() - environ['VIRTUALENV_NO_DOWNLOAD'] = '1' - command = ['virtualenv', '--no-site-packages', '--python', sys.executable, venv_path] - subprocess.check_call(command, stdout=stdout, env=environ) - else: - # Use embedded venv module in Python 3 - command = [sys.executable, '-m', 'venv', venv_path] - subprocess.check_call(command, stdout=stdout) - - -if __name__ == '__main__': - create_venv(*sys.argv[1:]) diff --git a/letsencrypt-auto-source/pieces/dependency-requirements.txt b/letsencrypt-auto-source/pieces/dependency-requirements.txt deleted file mode 100644 index f7a517e06..000000000 --- a/letsencrypt-auto-source/pieces/dependency-requirements.txt +++ /dev/null @@ -1,264 +0,0 @@ -# This is the flattened list of packages certbot-auto installs. -# To generate this, do (with docker and package hashin installed): -# ``` -# letsencrypt-auto-source/rebuild_dependencies.py \ -# letsencrypt-auto-source/pieces/dependency-requirements.txt -# ``` -# If you want to update a single dependency, run commands similar to these: -# ``` -# pip install hashin -# hashin -r dependency-requirements.txt cryptography==1.5.2 -# ``` -ConfigArgParse==1.2.3 \ - --hash=sha256:edd17be986d5c1ba2e307150b8e5f5107aba125f3574dddd02c85d5cdcfd37dc -certifi==2020.4.5.1 \ - --hash=sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304 \ - --hash=sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519 -cffi==1.14.0 \ - --hash=sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff \ - --hash=sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b \ - --hash=sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac \ - --hash=sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0 \ - --hash=sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384 \ - --hash=sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26 \ - --hash=sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6 \ - --hash=sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b \ - --hash=sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e \ - --hash=sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd \ - --hash=sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2 \ - --hash=sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66 \ - --hash=sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc \ - --hash=sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8 \ - --hash=sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55 \ - --hash=sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4 \ - --hash=sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5 \ - --hash=sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d \ - --hash=sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78 \ - --hash=sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa \ - --hash=sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793 \ - --hash=sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f \ - --hash=sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a \ - --hash=sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f \ - --hash=sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30 \ - --hash=sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f \ - --hash=sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3 \ - --hash=sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c -chardet==3.0.4 \ - --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ - --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 -configobj==5.0.6 \ - --hash=sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902 -cryptography==2.8 \ - --hash=sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c \ - --hash=sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595 \ - --hash=sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad \ - --hash=sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651 \ - --hash=sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2 \ - --hash=sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff \ - --hash=sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d \ - --hash=sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42 \ - --hash=sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d \ - --hash=sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e \ - --hash=sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912 \ - --hash=sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793 \ - --hash=sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13 \ - --hash=sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7 \ - --hash=sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0 \ - --hash=sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879 \ - --hash=sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f \ - --hash=sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9 \ - --hash=sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2 \ - --hash=sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf \ - --hash=sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8 -distro==1.5.0 \ - --hash=sha256:0e58756ae38fbd8fc3020d54badb8eae17c5b9dcbed388b17bb55b8a5928df92 \ - --hash=sha256:df74eed763e18d10d0da624258524ae80486432cd17392d9c3d96f5e83cd2799 -enum34==1.1.10; python_version < '3.4' \ - --hash=sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53 \ - --hash=sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328 \ - --hash=sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248 -funcsigs==1.0.2 \ - --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \ - --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50 -idna==2.9 \ - --hash=sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb \ - --hash=sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa -ipaddress==1.0.23 \ - --hash=sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc \ - --hash=sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2 -josepy==1.3.0 \ - --hash=sha256:c341ffa403399b18e9eae9012f804843045764d1390f9cb4648980a7569b1619 \ - --hash=sha256:e54882c64be12a2a76533f73d33cba9e331950fda9e2731e843490b774e7a01c -mock==1.3.0 \ - --hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6 \ - --hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb -parsedatetime==2.5 \ - --hash=sha256:3b835fc54e472c17ef447be37458b400e3fefdf14bb1ffdedb5d2c853acf4ba1 \ - --hash=sha256:d2e9ddb1e463de871d32088a3f3cea3dc8282b1b2800e081bd0ef86900451667 -pbr==5.4.5 \ - --hash=sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c \ - --hash=sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8 -pyOpenSSL==19.1.0 \ - --hash=sha256:621880965a720b8ece2f1b2f54ea2071966ab00e2970ad2ce11d596102063504 \ - --hash=sha256:9a24494b2602aaf402be5c9e30a0b82d4a5c67528fe8fb475e3f3bc00dd69507 -pyRFC3339==1.1 \ - --hash=sha256:67196cb83b470709c580bb4738b83165e67c6cc60e1f2e4f286cfcb402a926f4 \ - --hash=sha256:81b8cbe1519cdb79bed04910dd6fa4e181faf8c88dff1e1b987b5f7ab23a5b1a -pycparser==2.20 \ - --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \ - --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 -pyparsing==2.4.7 \ - --hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \ - --hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b -python-augeas==0.5.0 \ - --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 -pytz==2020.1 \ - --hash=sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed \ - --hash=sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048 -requests==2.23.0 \ - --hash=sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee \ - --hash=sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6 -requests-toolbelt==0.9.1 \ - --hash=sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f \ - --hash=sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0 -six==1.15.0 \ - --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ - --hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced -urllib3==1.25.9 \ - --hash=sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527 \ - --hash=sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115 -zope.component==4.6.1 \ - --hash=sha256:bfbe55d4a93e70a78b10edc3aad4de31bb8860919b7cbd8d66f717f7d7b279ac \ - --hash=sha256:d9c7c27673d787faff8a83797ce34d6ebcae26a370e25bddb465ac2182766aca -zope.deferredimport==4.3.1 \ - --hash=sha256:57b2345e7b5eef47efcd4f634ff16c93e4265de3dcf325afc7315ade48d909e1 \ - --hash=sha256:9a0c211df44aa95f1c4e6d2626f90b400f56989180d3ef96032d708da3d23e0a -zope.deprecation==4.4.0 \ - --hash=sha256:0d453338f04bacf91bbfba545d8bcdf529aa829e67b705eac8c1a7fdce66e2df \ - --hash=sha256:f1480b74995958b24ce37b0ef04d3663d2683e5d6debc96726eff18acf4ea113 -zope.event==4.4 \ - --hash=sha256:69c27debad9bdacd9ce9b735dad382142281ac770c4a432b533d6d65c4614bcf \ - --hash=sha256:d8e97d165fd5a0997b45f5303ae11ea3338becfe68c401dd88ffd2113fe5cae7 -zope.hookable==5.0.1 \ - --hash=sha256:0194b9b9e7f614abba60c90b231908861036578297515d3d6508eb10190f266d \ - --hash=sha256:0c2977473918bdefc6fa8dfb311f154e7f13c6133957fe649704deca79b92093 \ - --hash=sha256:17b8bdb3b77e03a152ca0d5ca185a7ae0156f5e5a2dbddf538676633a1f7380f \ - --hash=sha256:29d07681a78042cdd15b268ae9decffed9ace68a53eebeb61d65ae931d158841 \ - --hash=sha256:36fb1b35d1150267cb0543a1ddd950c0bc2c75ed0e6e92e3aaa6ac2e29416cb7 \ - --hash=sha256:3aed60c2bb5e812bbf9295c70f25b17ac37c233f30447a96c67913ba5073642f \ - --hash=sha256:3cac1565cc768911e72ca9ec4ddf5c5109e1fef0104f19f06649cf1874943b60 \ - --hash=sha256:3d4bc0cc4a37c3cd3081063142eeb2125511db3c13f6dc932d899c512690378e \ - --hash=sha256:3f73096f27b8c28be53ffb6604f7b570fbbb82f273c6febe5f58119009b59898 \ - --hash=sha256:522d1153d93f2d48aa0bd9fb778d8d4500be2e4dcf86c3150768f0e3adbbc4ef \ - --hash=sha256:523d2928fb7377bbdbc9af9c0b14ad73e6eaf226349f105733bdae27efd15b5a \ - --hash=sha256:5848309d4fc5c02150a45e8f8d2227e5bfda386a508bbd3160fed7c633c5a2fa \ - --hash=sha256:6781f86e6d54a110980a76e761eb54590630fd2af2a17d7edf02a079d2646c1d \ - --hash=sha256:6fd27921ebf3aaa945fa25d790f1f2046204f24dba4946f82f5f0a442577c3e9 \ - --hash=sha256:70d581862863f6bf9e175e85c9d70c2d7155f53fb04dcdb2f73cf288ca559a53 \ - --hash=sha256:81867c23b0dc66c8366f351d00923f2bc5902820a24c2534dfd7bf01a5879963 \ - --hash=sha256:81db29edadcbb740cd2716c95a297893a546ed89db1bfe9110168732d7f0afdd \ - --hash=sha256:86bd12624068cea60860a0759af5e2c3adc89c12aef6f71cf12f577e28deefe3 \ - --hash=sha256:9c184d8f9f7a76e1ced99855ccf390ffdd0ec3765e5cbf7b9cada600accc0a1e \ - --hash=sha256:acc789e8c29c13555e43fe4bf9fcd15a65512c9645e97bbaa5602e3201252b02 \ - --hash=sha256:afaa740206b7660d4cc3b8f120426c85761f51379af7a5b05451f624ad12b0af \ - --hash=sha256:b5f5fa323f878bb16eae68ea1ba7f6c0419d4695d0248bed4b18f51d7ce5ab85 \ - --hash=sha256:bd89e0e2c67bf4ac3aca2a19702b1a37269fb1923827f68324ac2e7afd6e3406 \ - --hash=sha256:c212de743283ec0735db24ec6ad913758df3af1b7217550ff270038062afd6ae \ - --hash=sha256:ca553f524293a0bdea05e7f44c3e685e4b7b022cb37d87bc4a3efa0f86587a8d \ - --hash=sha256:cab67065a3db92f636128d3157cc5424a145f82d96fb47159c539132833a6d36 \ - --hash=sha256:d3b3b3eedfdbf6b02898216e85aa6baf50207f4378a2a6803d6d47650cd37031 \ - --hash=sha256:d9f4a5a72f40256b686d31c5c0b1fde503172307beb12c1568296e76118e402c \ - --hash=sha256:df5067d87aaa111ed5d050e1ee853ba284969497f91806efd42425f5348f1c06 \ - --hash=sha256:e2587644812c6138f05b8a41594a8337c6790e3baf9a01915e52438c13fc6bef \ - --hash=sha256:e27fd877662db94f897f3fd532ef211ca4901eb1a70ba456f15c0866a985464a \ - --hash=sha256:e427ebbdd223c72e06ba94c004bb04e996c84dec8a0fa84e837556ae145c439e \ - --hash=sha256:e583ad4309c203ef75a09d43434cf9c2b4fa247997ecb0dcad769982c39411c7 \ - --hash=sha256:e760b2bc8ece9200804f0c2b64d10147ecaf18455a2a90827fbec4c9d84f3ad5 \ - --hash=sha256:ea9a9cc8bcc70e18023f30fa2f53d11ae069572a162791224e60cd65df55fb69 \ - --hash=sha256:ecb3f17dce4803c1099bd21742cd126b59817a4e76a6544d31d2cca6e30dbffd \ - --hash=sha256:ed794e3b3de42486d30444fb60b5561e724ee8a2d1b17b0c2e0f81e3ddaf7a87 \ - --hash=sha256:ee885d347279e38226d0a437b6a932f207f691c502ee565aba27a7022f1285df \ - --hash=sha256:fd5e7bc5f24f7e3d490698f7b854659a9851da2187414617cd5ed360af7efd63 \ - --hash=sha256:fe45f6870f7588ac7b2763ff1ce98cce59369717afe70cc353ec5218bc854bcc -zope.interface==5.1.0 \ - --hash=sha256:0103cba5ed09f27d2e3de7e48bb320338592e2fabc5ce1432cf33808eb2dfd8b \ - --hash=sha256:14415d6979356629f1c386c8c4249b4d0082f2ea7f75871ebad2e29584bd16c5 \ - --hash=sha256:1ae4693ccee94c6e0c88a4568fb3b34af8871c60f5ba30cf9f94977ed0e53ddd \ - --hash=sha256:1b87ed2dc05cb835138f6a6e3595593fea3564d712cb2eb2de963a41fd35758c \ - --hash=sha256:269b27f60bcf45438e8683269f8ecd1235fa13e5411de93dae3b9ee4fe7f7bc7 \ - --hash=sha256:27d287e61639d692563d9dab76bafe071fbeb26818dd6a32a0022f3f7ca884b5 \ - --hash=sha256:39106649c3082972106f930766ae23d1464a73b7d30b3698c986f74bf1256a34 \ - --hash=sha256:40e4c42bd27ed3c11b2c983fecfb03356fae1209de10686d03c02c8696a1d90e \ - --hash=sha256:461d4339b3b8f3335d7e2c90ce335eb275488c587b61aca4b305196dde2ff086 \ - --hash=sha256:4f98f70328bc788c86a6a1a8a14b0ea979f81ae6015dd6c72978f1feff70ecda \ - --hash=sha256:558a20a0845d1a5dc6ff87cd0f63d7dac982d7c3be05d2ffb6322a87c17fa286 \ - --hash=sha256:562dccd37acec149458c1791da459f130c6cf8902c94c93b8d47c6337b9fb826 \ - --hash=sha256:5e86c66a6dea8ab6152e83b0facc856dc4d435fe0f872f01d66ce0a2131b7f1d \ - --hash=sha256:60a207efcd8c11d6bbeb7862e33418fba4e4ad79846d88d160d7231fcb42a5ee \ - --hash=sha256:645a7092b77fdbc3f68d3cc98f9d3e71510e419f54019d6e282328c0dd140dcd \ - --hash=sha256:6874367586c020705a44eecdad5d6b587c64b892e34305bb6ed87c9bbe22a5e9 \ - --hash=sha256:74bf0a4f9091131de09286f9a605db449840e313753949fe07c8d0fe7659ad1e \ - --hash=sha256:7b726194f938791a6691c7592c8b9e805fc6d1b9632a833b9c0640828cd49cbc \ - --hash=sha256:8149ded7f90154fdc1a40e0c8975df58041a6f693b8f7edcd9348484e9dc17fe \ - --hash=sha256:8cccf7057c7d19064a9e27660f5aec4e5c4001ffcf653a47531bde19b5aa2a8a \ - --hash=sha256:911714b08b63d155f9c948da2b5534b223a1a4fc50bb67139ab68b277c938578 \ - --hash=sha256:a5f8f85986197d1dd6444763c4a15c991bfed86d835a1f6f7d476f7198d5f56a \ - --hash=sha256:a744132d0abaa854d1aad50ba9bc64e79c6f835b3e92521db4235a1991176813 \ - --hash=sha256:af2c14efc0bb0e91af63d00080ccc067866fb8cbbaca2b0438ab4105f5e0f08d \ - --hash=sha256:b054eb0a8aa712c8e9030065a59b5e6a5cf0746ecdb5f087cca5ec7685690c19 \ - --hash=sha256:b0becb75418f8a130e9d465e718316cd17c7a8acce6fe8fe07adc72762bee425 \ - --hash=sha256:b1d2ed1cbda2ae107283befd9284e650d840f8f7568cb9060b5466d25dc48975 \ - --hash=sha256:ba4261c8ad00b49d48bbb3b5af388bb7576edfc0ca50a49c11dcb77caa1d897e \ - --hash=sha256:d1fe9d7d09bb07228650903d6a9dc48ea649e3b8c69b1d263419cc722b3938e8 \ - --hash=sha256:d7804f6a71fc2dda888ef2de266727ec2f3915373d5a785ed4ddc603bbc91e08 \ - --hash=sha256:da2844fba024dd58eaa712561da47dcd1e7ad544a257482392472eae1c86d5e5 \ - --hash=sha256:dcefc97d1daf8d55199420e9162ab584ed0893a109f45e438b9794ced44c9fd0 \ - --hash=sha256:dd98c436a1fc56f48c70882cc243df89ad036210d871c7427dc164b31500dc11 \ - --hash=sha256:e74671e43ed4569fbd7989e5eecc7d06dc134b571872ab1d5a88f4a123814e9f \ - --hash=sha256:eb9b92f456ff3ec746cd4935b73c1117538d6124b8617bc0fe6fda0b3816e345 \ - --hash=sha256:ebb4e637a1fb861c34e48a00d03cffa9234f42bef923aec44e5625ffb9a8e8f9 \ - --hash=sha256:ef739fe89e7f43fb6494a43b1878a36273e5924869ba1d866f752c5812ae8d58 \ - --hash=sha256:f40db0e02a8157d2b90857c24d89b6310f9b6c3642369852cdc3b5ac49b92afc \ - --hash=sha256:f68bf937f113b88c866d090fea0bc52a098695173fc613b055a17ff0cf9683b6 \ - --hash=sha256:fb55c182a3f7b84c1a2d6de5fa7b1a05d4660d866b91dbf8d74549c57a1499e8 -zope.proxy==4.3.5 \ - --hash=sha256:00573dfa755d0703ab84bb23cb6ecf97bb683c34b340d4df76651f97b0bab068 \ - --hash=sha256:092049280f2848d2ba1b57b71fe04881762a220a97b65288bcb0968bb199ec30 \ - --hash=sha256:0cbd27b4d3718b5ec74fc65ffa53c78d34c65c6fd9411b8352d2a4f855220cf1 \ - --hash=sha256:17fc7e16d0c81f833a138818a30f366696653d521febc8e892858041c4d88785 \ - --hash=sha256:19577dfeb70e8a67249ba92c8ad20589a1a2d86a8d693647fa8385408a4c17b0 \ - --hash=sha256:207aa914576b1181597a1516e1b90599dc690c095343ae281b0772e44945e6a4 \ - --hash=sha256:219a7db5ed53e523eb4a4769f13105118b6d5b04ed169a283c9775af221e231f \ - --hash=sha256:2b50ea79849e46b5f4f2b0247a3687505d32d161eeb16a75f6f7e6cd81936e43 \ - --hash=sha256:5903d38362b6c716e66bbe470f190579c530a5baf03dbc8500e5c2357aa569a5 \ - --hash=sha256:5c24903675e271bd688c6e9e7df5775ac6b168feb87dbe0e4bcc90805f21b28f \ - --hash=sha256:5ef6bc5ed98139e084f4e91100f2b098a0cd3493d4e76f9d6b3f7b95d7ad0f06 \ - --hash=sha256:61b55ae3c23a126a788b33ffb18f37d6668e79a05e756588d9e4d4be7246ab1c \ - --hash=sha256:63ddb992931a5e616c87d3d89f5a58db086e617548005c7f9059fac68c03a5cc \ - --hash=sha256:6943da9c09870490dcfd50c4909c0cc19f434fa6948f61282dc9cb07bcf08160 \ - --hash=sha256:6ad40f85c1207803d581d5d75e9ea25327cd524925699a83dfc03bf8e4ba72b7 \ - --hash=sha256:6b44433a79bdd7af0e3337bd7bbcf53dd1f9b0fa66bf21bcb756060ce32a96c1 \ - --hash=sha256:6bbaa245015d933a4172395baad7874373f162955d73612f0b66b6c2c33b6366 \ - --hash=sha256:7007227f4ea85b40a2f5e5a244479f6a6dfcf906db9b55e812a814a8f0e2c28d \ - --hash=sha256:74884a0aec1f1609190ec8b34b5d58fb3b5353cf22b96161e13e0e835f13518f \ - --hash=sha256:7d25fe5571ddb16369054f54cdd883f23de9941476d97f2b92eb6d7d83afe22d \ - --hash=sha256:7e162bdc5e3baad26b2262240be7d2bab36991d85a6a556e48b9dfb402370261 \ - --hash=sha256:814d62678dc3a30f4aa081982d830b7c342cf230ffc9d030b020cb154eeebf9e \ - --hash=sha256:8878a34c5313ee52e20aa50b03138af8d472bae465710fb954d133a9bfd3c38d \ - --hash=sha256:a66a0d94e5b081d5d695e66d6667e91e74d79e273eee95c1747717ba9cb70792 \ - --hash=sha256:a69f5cbf4addcfdf03dda564a671040127a6b7c34cf9fe4973582e68441b63fa \ - --hash=sha256:b00f9f0c334d07709d3f73a7cb8ae63c6ca1a90c790a63b5e7effa666ef96021 \ - --hash=sha256:b6ed71e4a7b4690447b626f499d978aa13197a0e592950e5d7020308f6054698 \ - --hash=sha256:bdf5041e5851526e885af579d2f455348dba68d74f14a32781933569a327fddf \ - --hash=sha256:be034360dd34e62608419f86e799c97d389c10a0e677a25f236a971b2f40dac9 \ - --hash=sha256:cc8f590a5eed30b314ae6b0232d925519ade433f663de79cc3783e4b10d662ba \ - --hash=sha256:cd7a318a15fe6cc4584bf3c4426f092ed08c0fd012cf2a9173114234fe193e11 \ - --hash=sha256:cf19b5f63a59c20306e034e691402b02055c8f4e38bf6792c23cad489162a642 \ - --hash=sha256:cfc781ce442ec407c841e9aa51d0e1024f72b6ec34caa8fdb6ef9576d549acf2 \ - --hash=sha256:dea9f6f8633571e18bc20cad83603072e697103a567f4b0738d52dd0211b4527 \ - --hash=sha256:e4a86a1d5eb2cce83c5972b3930c7c1eac81ab3508464345e2b8e54f119d5505 \ - --hash=sha256:e7106374d4a74ed9ff00c46cc00f0a9f06a0775f8868e423f85d4464d2333679 \ - --hash=sha256:e98a8a585b5668aa9e34d10f7785abf9545fe72663b4bfc16c99a115185ae6a5 \ - --hash=sha256:f64840e68483316eb58d82c376ad3585ca995e69e33b230436de0cdddf7363f9 \ - --hash=sha256:f8f4b0a9e6683e43889852130595c8854d8ae237f2324a053cdd884de936aa9b \ - --hash=sha256:fc45a53219ed30a7f670a6d8c98527af0020e6fd4ee4c0a8fb59f147f06d816c diff --git a/letsencrypt-auto-source/pieces/fetch.py b/letsencrypt-auto-source/pieces/fetch.py deleted file mode 100644 index 1515fe353..000000000 --- a/letsencrypt-auto-source/pieces/fetch.py +++ /dev/null @@ -1,148 +0,0 @@ -"""Do downloading and JSON parsing without additional dependencies. :: - - # Print latest released version of LE to stdout: - python fetch.py --latest-version - - # Download letsencrypt-auto script from git tag v1.2.3 into the folder I'm - # in, and make sure its signature verifies: - python fetch.py --le-auto-script v1.2.3 - -On failure, return non-zero. - -""" - -from __future__ import print_function, unicode_literals - -from distutils.version import LooseVersion -from json import loads -from os import devnull, environ -from os.path import dirname, join -import re -import ssl -from subprocess import check_call, CalledProcessError -from sys import argv, exit -try: - from urllib2 import build_opener, HTTPHandler, HTTPSHandler - from urllib2 import HTTPError, URLError -except ImportError: - from urllib.request import build_opener, HTTPHandler, HTTPSHandler - from urllib.error import HTTPError, URLError - -PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq -OzQb2eyW15YFjDDEMI0ZOzt8f504obNs920lDnpPD2/KqgsfjOgw2K7xWDJIj/18 -xUvWPk3LDkrnokNiRkA3KOx3W6fHycKL+zID7zy+xZYBuh2fLyQtWV1VGQ45iNRp -9+Zo7rH86cdfgkdnWTlNSHyTLW9NbXvyv/E12bppPcEvgCTAQXgnDVJ0/sqmeiij -n9tTFh03aM+R2V/21h8aTraAS24qiPCz6gkmYGC8yr6mglcnNoYbsLNYZ69zF1XH -cXPduCPdPdfLlzVlKK1/U7hkA28eG3BIAMh6uJYBRJTpiGgaGdPd7YekUB8S6cy+ -CQIDAQAB ------END PUBLIC KEY----- -""") - -class ExpectedError(Exception): - """A novice-readable exception that also carries the original exception for - debugging""" - - -class HttpsGetter(object): - def __init__(self): - """Build an HTTPS opener.""" - # Based on pip 1.4.1's URLOpener - # This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set. - if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'): - self._opener = build_opener(HTTPSHandler(context=cert_none_context())) - else: - self._opener = build_opener(HTTPSHandler()) - # Strip out HTTPHandler to prevent MITM spoof: - for handler in self._opener.handlers: - if isinstance(handler, HTTPHandler): - self._opener.handlers.remove(handler) - - def get(self, url): - """Return the document contents pointed to by an HTTPS URL. - - If something goes wrong (404, timeout, etc.), raise ExpectedError. - - """ - try: - # socket module docs say default timeout is None: that is, no - # timeout - return self._opener.open(url, timeout=30).read() - except (HTTPError, IOError) as exc: - raise ExpectedError("Couldn't download %s." % url, exc) - - -def write(contents, dir, filename): - """Write something to a file in a certain directory.""" - with open(join(dir, filename), 'wb') as file: - file.write(contents) - - -def latest_stable_version(get): - """Return the latest stable release of letsencrypt.""" - metadata = loads(get( - environ.get('LE_AUTO_JSON_URL', - 'https://pypi.python.org/pypi/certbot/json')).decode('UTF-8')) - # metadata['info']['version'] actually returns the latest of any kind of - # release release, contrary to https://wiki.python.org/moin/PyPIJSON. - # The regex is a sufficient regex for picking out prereleases for most - # packages, LE included. - return str(max(LooseVersion(r) for r - in metadata['releases'].keys() - if re.match('^[0-9.]+$', r))) - - -def verified_new_le_auto(get, tag, temp_dir): - """Return the path to a verified, up-to-date letsencrypt-auto script. - - If the download's signature does not verify or something else goes wrong - with the verification process, raise ExpectedError. - - """ - le_auto_dir = environ.get( - 'LE_AUTO_DIR_TEMPLATE', - 'https://raw.githubusercontent.com/certbot/certbot/%s/' - 'letsencrypt-auto-source/') % tag - write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto') - write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig') - write(PUBLIC_KEY.encode('UTF-8'), temp_dir, 'public_key.pem') - try: - with open(devnull, 'w') as dev_null: - check_call(['openssl', 'dgst', '-sha256', '-verify', - join(temp_dir, 'public_key.pem'), - '-signature', - join(temp_dir, 'letsencrypt-auto.sig'), - join(temp_dir, 'letsencrypt-auto')], - stdout=dev_null, - stderr=dev_null) - except CalledProcessError as exc: - raise ExpectedError("Couldn't verify signature of downloaded " - "certbot-auto.", exc) - - -def cert_none_context(): - """Create a SSLContext object to not check hostname.""" - # PROTOCOL_TLS isn't available before 2.7.13 but this code is for 2.7.9+, so use this. - context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - context.verify_mode = ssl.CERT_NONE - return context - - -def main(): - get = HttpsGetter().get - flag = argv[1] - try: - if flag == '--latest-version': - print(latest_stable_version(get)) - elif flag == '--le-auto-script': - tag = argv[2] - verified_new_le_auto(get, tag, dirname(argv[0])) - except ExpectedError as exc: - print(exc.args[0], exc.args[1]) - return 1 - else: - return 0 - - -if __name__ == '__main__': - exit(main()) diff --git a/letsencrypt-auto-source/pieces/letsencrypt-requirements.txt b/letsencrypt-auto-source/pieces/letsencrypt-requirements.txt deleted file mode 100644 index 8e745c9cd..000000000 --- a/letsencrypt-auto-source/pieces/letsencrypt-requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Contains the requirements for the letsencrypt package. -# -# Since the letsencrypt package depends on certbot and using pip with hashes -# requires that all installed packages have hashes listed, this allows -# dependency-requirements.txt to be used without requiring a hash for a -# (potentially unreleased) Certbot package. - -letsencrypt==0.7.0 \ - --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ - --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 diff --git a/letsencrypt-auto-source/pieces/pipstrap.py b/letsencrypt-auto-source/pieces/pipstrap.py deleted file mode 100755 index 7610c2686..000000000 --- a/letsencrypt-auto-source/pieces/pipstrap.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python -"""A small script that can act as a trust root for installing pip >=8 -Embed this in your project, and your VCS checkout is all you have to trust. In -a post-peep era, this lets you claw your way to a hash-checking version of pip, -with which you can install the rest of your dependencies safely. All it assumes -is Python 2.6 or better and *some* version of pip already installed. If -anything goes wrong, it will exit with a non-zero status code. -""" -# This is here so embedded copies are MIT-compliant: -# Copyright (c) 2016 Erik Rose -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -from __future__ import print_function -from distutils.version import StrictVersion -from hashlib import sha256 -from os import environ -from os.path import join -from shutil import rmtree -try: - from subprocess import check_output -except ImportError: - from subprocess import CalledProcessError, PIPE, Popen - - def check_output(*popenargs, **kwargs): - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be ' - 'overridden.') - process = Popen(stdout=PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise CalledProcessError(retcode, cmd) - return output -import sys -from tempfile import mkdtemp -try: - from urllib2 import build_opener, HTTPHandler, HTTPSHandler -except ImportError: - from urllib.request import build_opener, HTTPHandler, HTTPSHandler -try: - from urlparse import urlparse -except ImportError: - from urllib.parse import urlparse # 3.4 - - -__version__ = 1, 5, 1 -PIP_VERSION = '9.0.1' -DEFAULT_INDEX_BASE = 'https://pypi.python.org' - - -# wheel has a conditional dependency on argparse: -maybe_argparse = ( - [('18/dd/e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/' - 'argparse-1.4.0.tar.gz', - '62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4')] - if sys.version_info < (2, 7, 0) else []) - - -# Be careful when updating the pinned versions here, in particular for pip. -# Indeed starting from 10.0, pip will build dependencies in isolation if the -# related projects are compliant with PEP 517. This is not something we want -# as of now, so the isolation build will need to be disabled wherever -# pipstrap is used (see https://github.com/certbot/certbot/issues/8256). -PACKAGES = maybe_argparse + [ - # Pip has no dependencies, as it vendors everything: - ('11/b6/abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/' - 'pip-{0}.tar.gz'.format(PIP_VERSION), - '09f243e1a7b461f654c26a725fa373211bb7ff17a9300058b205c61658ca940d'), - # This version of setuptools has only optional dependencies: - ('37/1b/b25507861991beeade31473868463dad0e58b1978c209de27384ae541b0b/' - 'setuptools-40.6.3.zip', - '3b474dad69c49f0d2d86696b68105f3a6f195f7ab655af12ef9a9c326d2b08f8'), - ('c9/1d/bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/' - 'wheel-0.29.0.tar.gz', - '1ebb8ad7e26b448e9caa4773d2357849bf80ff9e313964bcaf79cbf0201a1648') -] - - -class HashError(Exception): - def __str__(self): - url, path, actual, expected = self.args - return ('{url} did not match the expected hash {expected}. Instead, ' - 'it was {actual}. The file (left at {path}) may have been ' - 'tampered with.'.format(**locals())) - - -def hashed_download(url, temp, digest): - """Download ``url`` to ``temp``, make sure it has the SHA-256 ``digest``, - and return its path.""" - # Based on pip 1.4.1's URLOpener but with cert verification removed. Python - # >=2.7.9 verifies HTTPS certs itself, and, in any case, the cert - # authenticity has only privacy (not arbitrary code execution) - # implications, since we're checking hashes. - def opener(using_https=True): - opener = build_opener(HTTPSHandler()) - if using_https: - # Strip out HTTPHandler to prevent MITM spoof: - for handler in opener.handlers: - if isinstance(handler, HTTPHandler): - opener.handlers.remove(handler) - return opener - - def read_chunks(response, chunk_size): - while True: - chunk = response.read(chunk_size) - if not chunk: - break - yield chunk - - parsed_url = urlparse(url) - response = opener(using_https=parsed_url.scheme == 'https').open(url) - path = join(temp, parsed_url.path.split('/')[-1]) - actual_hash = sha256() - with open(path, 'wb') as file: - for chunk in read_chunks(response, 4096): - file.write(chunk) - actual_hash.update(chunk) - - actual_digest = actual_hash.hexdigest() - if actual_digest != digest: - raise HashError(url, path, actual_digest, digest) - return path - - -def get_index_base(): - """Return the URL to the dir containing the "packages" folder. - Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the - end if it's there; that is likely to give us the right dir. - """ - env_var = environ.get('PIP_INDEX_URL', '').rstrip('/') - if env_var: - SIMPLE = '/simple' - if env_var.endswith(SIMPLE): - return env_var[:-len(SIMPLE)] - else: - return env_var - else: - return DEFAULT_INDEX_BASE - - -def main(): - python = sys.executable or 'python' - pip_version = StrictVersion(check_output([python, '-m', 'pip', '--version']) - .decode('utf-8').split()[1]) - has_pip_cache = pip_version >= StrictVersion('6.0') - index_base = get_index_base() - temp = mkdtemp(prefix='pipstrap-') - try: - downloads = [hashed_download(index_base + '/packages/' + path, - temp, - digest) - for path, digest in PACKAGES] - # Calling pip as a module is the preferred way to avoid problems about pip self-upgrade. - command = [python, '-m', 'pip', 'install', '--no-index', '--no-deps', '-U'] - # Disable cache since it is not used and it otherwise sometimes throws permission warnings: - command.extend(['--no-cache-dir'] if has_pip_cache else []) - command.extend(downloads) - check_output(command) - except HashError as exc: - print(exc) - except Exception: - rmtree(temp) - raise - else: - rmtree(temp) - return 0 - return 1 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/letsencrypt-auto-source/tests/signing.key b/letsencrypt-auto-source/tests/signing.key deleted file mode 100644 index b9964d00c..000000000 --- a/letsencrypt-auto-source/tests/signing.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEAsMoSzLYQ7E1sdSOkwelgtzKIh2qi3bpXuYtcfFC0XrvWig07 -1NwIj+dZiT0OLZ2hPispEH0B7ISuuWg1ll7GhFW0VdbxL6JdGzS2ShNWkX9hE9z+ -j8VqwDPOBn3ZHm03qwpYkBDwQib3KqOdYbTTuUtJmmGcuk3a9Aq/sCT6DdfmTSdP -5asdQYwIcaQreDrOosaS84DTWI3IU+UYJVglLsIVPBuy9IcgHidUQ96hJnoPsDCW -sHwX62495QKEarauyKQrJzFes0EY95orDM47Z5o/NDiQB11m91yNB0MmPYY9QSbn -OA9j7IaaC97AwRLuwXY+/R2ablTcxurWou68iQIDAQABAoIBAQCJE3W2Mqk2f+XL -geKa1BjAkzcXQJCduYGRhUQlw/HGzoBPtGki56Tf53MeHTAkIGfIq3CAr1zRhiNv -8SQzvrLQIx/buvhxhcQJdzqsfwgNcqXT3/OliF34P3LMx8GUfPy/6xq2Qdv4fvwA -nLJH8wyDTKP6RxtdvUY7GSZ+Ln2QQv/3Nco7tax4GHNGom8iSgeH/YKTDnvitdqh -a0fr930QzU39TfOftLmasdmKUOIg8G2wr4Sy6Kn060+OUoQr1fZF5mnLvvQeILCK -uav91JkIeMLggzk+t88IJUFWdOoxv5hWTnNzHyt+/GYfovyRz2fKQMwzdh1F8iM5 -+867rEb9AoGBANn1ncemJBedDshStdCBUH0+2ExPrawveaXOZKnx8/VGFXNi0hAf -KzkntMWd5g5kB077FtKO9CYTBvK4pZBWIFLcJEqAz88JeXME6dfUbRucDr72ko+l -rcLHXj7F0IDVzj/9CphMGAhC9J/4YW9SPcSbMw6dQ6xOk73f1Vowve0DAoGBAM+k -/F+hVqCS3f22Bg9KuDtx+zCydaZxC842DgIkV1SO2iFhNHjnpQ5EIR0WrSYeV2n+ -rD7kVs5OH1HvnGScHaQKtAVqZClSwF14jzE+Aj8XDwxiHLSOhJgKlzfVX7h1ymMh -7fsslDl6xNGQ+40gubhkCLT5qABFKy1mrZ8b+3yDAoGAGLGUI6d2FVrM7vM3+Bx+ -gwIYvWSVl5l1XcypaPupmRNMoNsEU6FEY2BVQcJm6yB4F4GpD0f0709ejSdQUq7/ -UIPydKJtaNZ49QgMelBt4B/pJ8eFyVKLAjNWQSRmQAJ5MJS5m5Gbc2wqjOk2GMen -idvPiAtXPHFWmb9/S42UJwMCgYEAjymAe2qgcGtyNNfIC8kHhqzKdEPGi/ALJKzu -MZnewEURrcv4QpfrnA9rCUQ2Mz7eJA1bsqz6EJmaTIK4wEFGynA6uDUnQ7pzOL7D -cz7+i4MZc/89LVvJnY5Hvk4WBfboiDq/etq8g3jatGaSmTYD9la6DhTHORB3eYD+ -meHQHYMCgYEA18y9hnx2k4vNeBei4YXF4pAvKdwKLQD+CcP9ljb3VT+kXktjRA1C -aWj3HhMwvcxtttfkQzEnwwGRAkTEtNewJ8KFxhmc9nYElZTNZ+SuHD5Dkv8xqoj8 -NvG8rU1eiEyPwE2wQxpM5JLqbo7IWtR0dmptjKoF1gRxn6Wh4TwEiHA= ------END RSA PRIVATE KEY----- diff --git a/tests/letstest/README.md b/tests/letstest/README.md index 76db57153..aea4e2e13 100644 --- a/tests/letstest/README.md +++ b/tests/letstest/README.md @@ -59,8 +59,7 @@ The tests take quite a while to run. Example scripts are in the 'scripts' directory, these are just bash scripts that have a few parameters passed to them at runtime via environment variables. test_apache2.sh is a useful reference. -Note that the
test_letsencrypt_auto_*
scripts pull code from PyPI using the letsencrypt-auto script, -__not__ the local python code. test_apache2 runs the dev venv and does local tests. +test_apache2 runs the dev venv and does local tests. See: - https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html diff --git a/tests/letstest/multitester.py b/tests/letstest/multitester.py index 8c0528990..360bb979e 100644 --- a/tests/letstest/multitester.py +++ b/tests/letstest/multitester.py @@ -22,7 +22,7 @@ Usage: >aws ec2 create-key-pair --profile HappyHacker --key-name MyKeyPair \ --query 'KeyMaterial' --output text > MyKeyPair.pem then: ->python multitester.py targets.yaml MyKeyPair.pem HappyHacker scripts/test_leauto_upgrades.sh +>python multitester.py targets.yaml MyKeyPair.pem HappyHacker scripts/test_sdists.sh see: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html https://docs.aws.amazon.com/cli/latest/userguide/cli-ec2-keypairs.html @@ -55,7 +55,7 @@ parser.add_argument('key_file', parser.add_argument('aws_profile', help='profile for AWS (i.e. as in ~/.aws/certificates)') parser.add_argument('test_script', - default='test_letsencrypt_auto_certonly_standalone.sh', + default='test_sdists.sh', help='path of bash script in to deploy and run') parser.add_argument('--repo', default='https://github.com/letsencrypt/letsencrypt.git', diff --git a/tests/letstest/scripts/test_leauto_upgrades.sh b/tests/letstest/scripts/test_leauto_upgrades.sh deleted file mode 100755 index 3964364e1..000000000 --- a/tests/letstest/scripts/test_leauto_upgrades.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/bash -xe -set -o pipefail - -# $OS_TYPE $PUBLIC_IP $PRIVATE_IP $PUBLIC_HOSTNAME -# are dynamically set at execution - -cd letsencrypt - -if ! command -v git ; then - if [ "$OS_TYPE" = "ubuntu" ] ; then - sudo apt-get update - fi - if ! ( sudo apt-get install -y git || sudo yum install -y git-all || sudo yum install -y git || sudo dnf install -y git ) ; then - echo git installation failed! - exit 1 - fi -fi -# If we're on a RHEL 6 based system, we can be confident Python is already -# installed because the package manager is written in Python. -if command -v python && [ $(python -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//') -eq 26 ]; then - # 0.20.0 is the latest version of letsencrypt-auto that doesn't install - # Python 3 on RHEL 6. - INITIAL_VERSION="0.20.0" - RUN_RHEL6_TESTS=1 -else - # 0.39.0 is the oldest version of letsencrypt-auto that works on CentOS 8. - INITIAL_VERSION="0.39.0" -fi - -git checkout -f "v$INITIAL_VERSION" letsencrypt-auto -if ! ./letsencrypt-auto -v --debug --version --no-self-upgrade 2>&1 | tail -n1 | grep "^certbot $INITIAL_VERSION$" ; then - echo initial installation appeared to fail - exit 1 -fi - -if command -v python; then - PYTHON_NAME="python" -else - PYTHON_NAME="python3" -fi - -# Now that python and openssl have been installed, we can set up a fake server -# to provide a new version of letsencrypt-auto. First, we start the server and -# directory to be served. -MY_TEMP_DIR=$(mktemp -d) -PORT_FILE="$MY_TEMP_DIR/port" -LOG_FILE="$MY_TEMP_DIR/log" -SERVER_PATH=$("$PYTHON_NAME" tools/readlink.py tools/simple_http_server.py) -cd "$MY_TEMP_DIR" -# We set PYTHONUNBUFFERED to disable buffering of output to LOG_FILE -PYTHONUNBUFFERED=1 "$PYTHON_NAME" "$SERVER_PATH" 0 > $PORT_FILE 2> "$LOG_FILE" & -SERVER_PID=$! -trap 'kill "$SERVER_PID" && rm -rf "$MY_TEMP_DIR"' EXIT -cd ~- - -# Then, we set up the files to be served. -FAKE_VERSION_NUM="99.99.99" -echo "{\"releases\": {\"$FAKE_VERSION_NUM\": null}}" > "$MY_TEMP_DIR/json" -LE_AUTO_SOURCE_DIR="$MY_TEMP_DIR/v$FAKE_VERSION_NUM" -NEW_LE_AUTO_PATH="$LE_AUTO_SOURCE_DIR/letsencrypt-auto" -mkdir "$LE_AUTO_SOURCE_DIR" -cp letsencrypt-auto-source/letsencrypt-auto "$LE_AUTO_SOURCE_DIR/letsencrypt-auto" -SIGNING_KEY="letsencrypt-auto-source/tests/signing.key" -openssl dgst -sha256 -sign "$SIGNING_KEY" -out "$NEW_LE_AUTO_PATH.sig" "$NEW_LE_AUTO_PATH" - -# Next, we wait for the server to start and get the port number. -sleep 5s -SERVER_PORT=$(sed -n 's/.*port \([0-9]\+\).*/\1/p' "$PORT_FILE") - -# Finally, we set the necessary certbot-auto environment variables. -export LE_AUTO_DIR_TEMPLATE="http://localhost:$SERVER_PORT/%s/" -export LE_AUTO_JSON_URL="http://localhost:$SERVER_PORT/json" -export LE_AUTO_PUBLIC_KEY="-----BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMoSzLYQ7E1sdSOkwelg -tzKIh2qi3bpXuYtcfFC0XrvWig071NwIj+dZiT0OLZ2hPispEH0B7ISuuWg1ll7G -hFW0VdbxL6JdGzS2ShNWkX9hE9z+j8VqwDPOBn3ZHm03qwpYkBDwQib3KqOdYbTT -uUtJmmGcuk3a9Aq/sCT6DdfmTSdP5asdQYwIcaQreDrOosaS84DTWI3IU+UYJVgl -LsIVPBuy9IcgHidUQ96hJnoPsDCWsHwX62495QKEarauyKQrJzFes0EY95orDM47 -Z5o/NDiQB11m91yNB0MmPYY9QSbnOA9j7IaaC97AwRLuwXY+/R2ablTcxurWou68 -iQIDAQAB ------END PUBLIC KEY----- -" - -if [ "$RUN_RHEL6_TESTS" = 1 ]; then - if command -v python3; then - echo "Didn't expect Python 3 to be installed!" - exit 1 - fi - cp letsencrypt-auto cb-auto - if ! ./cb-auto -v --debug --version 2>&1 | grep "$INITIAL_VERSION" ; then - echo "Certbot shouldn't have updated to a new version!" - exit 1 - fi - # Create a 2nd venv at the old path to ensure we properly handle the (unlikely) case of two separate virtual environments below. - HOME=${HOME:-~root} - XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share} - OLD_VENV_PATH="$XDG_DATA_HOME/letsencrypt" - export VENV_PATH="$OLD_VENV_PATH" - if ! sudo -E ./letsencrypt-auto -v --debug --version --no-self-upgrade 2>&1 | tail -n1 | grep "^certbot $INITIAL_VERSION$" ; then - echo second installation appeared to fail - exit 1 - fi - unset VENV_PATH -fi - -if ./letsencrypt-auto -v --debug --version | grep "WARNING: couldn't find Python" ; then - echo "Had problems checking for updates!" - exit 1 -fi - -# Since certbot-auto is deprecated, we expect it to leave existing Certbot -# installations unmodified so we check for the same version that was initially -# installed below. -EXPECTED_VERSION="$INITIAL_VERSION" - -if ! /opt/eff.org/certbot/venv/bin/letsencrypt --version 2>&1 | tail -n1 | grep "^certbot $EXPECTED_VERSION$" ; then - echo unexpected certbot version found - exit 1 -fi - -if ! diff letsencrypt-auto letsencrypt-auto-source/letsencrypt-auto ; then - echo letsencrypt-auto and letsencrypt-auto-source/letsencrypt-auto differ - exit 1 -fi - -# Now let's test if letsencrypt-auto still tries to upgrade to a new version. -# Regardless of the OS, versions of the script with development version numbers -# ending in .dev0 will not upgrade. See -# https://github.com/certbot/certbot/blob/bdfb9f19c4086a60ef010d2431768850c26d838a/certbot-auto#L1947-L1948. -# In order to test the process of different OSes setting NO_SELF_UPGRADE as -# part of the script's deprecation, we make use of the fact that -# letsencrypt-auto should still attempt to fetch the version number from PyPI -# even if it has a development version number unless NO_SELF_UPGRADE is set in -# which case all of that logic should be skipped. -# -# First we make a copy of the current server logs. -PREVIOUS_LOG_FILE="$MY_TEMP_DIR/previous-log" -cp "$LOG_FILE" "$PREVIOUS_LOG_FILE" - -# Next we run letsencrypt-auto and make sure there were no problems checking -# for updates, the Certbot install still works, the version number is what -# we expect, and it prints a message about not receiving updates. -if ./letsencrypt-auto -v --debug --version | grep "WARNING: couldn't find Python" ; then - echo "Had problems checking for updates!" - exit 1 -fi -if ! ./letsencrypt-auto -v --debug --version 2>&1 | tail -n1 | grep "^certbot $EXPECTED_VERSION$" ; then - echo unexpected certbot version found - exit 1 -fi -if ! ./letsencrypt-auto -v --debug --version 2>&1 | grep "will no longer receive updates" ; then - echo script did not print warning about not receiving updates! - exit 1 -fi - -# Finally, we check if our local server received more requests. -if ! diff "$LOG_FILE" "$PREVIOUS_LOG_FILE" ; then - echo our local server received unexpected requests - exit 1 -fi diff --git a/tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh b/tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh deleted file mode 100755 index 9573ab690..000000000 --- a/tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -x -set -eo pipefail - -# $PUBLIC_IP $PRIVATE_IP $PUBLIC_HOSTNAME are dynamically set at execution - -# with curl, instance metadata available from EC2 metadata service: -#public_host=$(curl -s http://169.254.169.254/2014-11-05/meta-data/public-hostname) -#public_ip=$(curl -s http://169.254.169.254/2014-11-05/meta-data/public-ipv4) -#private_ip=$(curl -s http://169.254.169.254/2014-11-05/meta-data/local-ipv4) - -cd letsencrypt -LE_AUTO_DIR="/usr/local/bin" -LE_AUTO_PATH="$LE_AUTO_DIR/letsencrypt-auto" -sudo cp letsencrypt-auto-source/letsencrypt-auto "$LE_AUTO_PATH" -sudo chown root "$LE_AUTO_PATH" -sudo chmod 0755 "$LE_AUTO_PATH" -export PATH="$LE_AUTO_DIR:$PATH" - -# Since certbot-auto is deprecated, we expect certbot-auto to error and -# refuse to install Certbot. -set +o pipefail -if ! letsencrypt-auto --debug --version | grep "Certbot cannot be installed."; then - echo "letsencrypt-auto didn't report being uninstallable." - exit 1 -fi -if [ ${PIPESTATUS[0]} != 1 ]; then - echo "letsencrypt-auto didn't exit with status 1 as expected" - exit 1 -fi diff --git a/tests/letstest/scripts/test_sdists.sh b/tests/letstest/scripts/test_sdists.sh index aa385ad2f..b0d53fb67 100755 --- a/tests/letstest/scripts/test_sdists.sh +++ b/tests/letstest/scripts/test_sdists.sh @@ -41,7 +41,7 @@ for pkg_dir in acme certbot $PLUGINS; do cd - done -VERSION=$(python letsencrypt-auto-source/version.py) +VERSION=$(python tests/letstest/scripts/version.py) # test sdists cd $TEMP_DIR for pkg in acme certbot $PLUGINS; do diff --git a/letsencrypt-auto-source/version.py b/tests/letstest/scripts/version.py similarity index 75% rename from letsencrypt-auto-source/version.py rename to tests/letstest/scripts/version.py index d70ffefac..dce2eaec2 100755 --- a/letsencrypt-auto-source/version.py +++ b/tests/letstest/scripts/version.py @@ -1,8 +1,7 @@ #!/usr/bin/env python """Get the current Certbot version number. -Provides simple utilities for determining the Certbot version number and -building letsencrypt-auto. +Provides a simple utility for determining the Certbot version number """ from __future__ import print_function @@ -10,10 +9,10 @@ from os.path import abspath, dirname, join import re -def certbot_version(build_script_dir): +def certbot_version(caller_dir): """Return the version number stamped in certbot/__init__.py.""" return re.search('''^__version__ = ['"](.+)['"].*''', - file_contents(join(dirname(build_script_dir), + file_contents(join(dirname(dirname(dirname(caller_dir))), 'certbot', 'certbot', '__init__.py')), diff --git a/tox.ini b/tox.ini index 90aecc1b3..f7db07b52 100644 --- a/tox.ini +++ b/tox.ini @@ -290,20 +290,6 @@ deps = {[testenv:test-farm-tests-base]deps} passenv = {[testenv:test-farm-tests-base]passenv} setenv = {[testenv:test-farm-tests-base]setenv} -[testenv:test-farm-leauto-upgrades] -changedir = {[testenv:test-farm-tests-base]changedir} -commands = {toxinidir}/tools/retry.sh python multitester.py auto_targets.yaml {env:AWS_EC2_PEM_FILE} SET_BY_ENV scripts/test_leauto_upgrades.sh --repo {toxinidir} -deps = {[testenv:test-farm-tests-base]deps} -passenv = {[testenv:test-farm-tests-base]passenv} -setenv = {[testenv:test-farm-tests-base]setenv} - -[testenv:test-farm-certonly-standalone] -changedir = {[testenv:test-farm-tests-base]changedir} -commands = {toxinidir}/tools/retry.sh python multitester.py auto_targets.yaml {env:AWS_EC2_PEM_FILE} SET_BY_ENV scripts/test_letsencrypt_auto_certonly_standalone.sh --repo {toxinidir} -deps = {[testenv:test-farm-tests-base]deps} -passenv = {[testenv:test-farm-tests-base]passenv} -setenv = {[testenv:test-farm-tests-base]setenv} - [testenv:test-farm-sdists] changedir = {[testenv:test-farm-tests-base]changedir} commands = {toxinidir}/tools/retry.sh python multitester.py targets.yaml {env:AWS_EC2_PEM_FILE} SET_BY_ENV scripts/test_sdists.sh --repo {toxinidir} From 2cf177586497724f0eebbbe85cfcb9432f6963cf Mon Sep 17 00:00:00 2001 From: Mads Jensen Date: Thu, 29 Apr 2021 02:45:08 +0200 Subject: [PATCH 05/16] Update assertTrue/False to Python 3 precise asserts (#8792) * Update assertTrue/False to Python 3 precise asserts * Fix test failures * Fix test failures * More replacements * Update to Python 3 asserts in acme-module * Fix Windows test failure * Fix failures * Fix test failure * More replacements * Don't include the semgrep rules * Fix test failure --- acme/tests/challenges_test.py | 4 +- acme/tests/client_test.py | 18 ++-- acme/tests/crypto_util_test.py | 6 +- acme/tests/errors_test.py | 4 +- acme/tests/jws_test.py | 4 +- acme/tests/messages_test.py | 20 ++-- certbot/tests/account_test.py | 2 +- certbot/tests/auth_handler_test.py | 16 +-- certbot/tests/cert_manager_test.py | 47 +++++---- certbot/tests/cli_test.py | 128 +++++++++++------------ certbot/tests/client_test.py | 28 ++--- certbot/tests/compat/filesystem_test.py | 40 +++---- certbot/tests/compat/misc_test.py | 2 +- certbot/tests/crypto_util_test.py | 14 +-- certbot/tests/display/completer_test.py | 8 +- certbot/tests/display/ops_test.py | 26 +++-- certbot/tests/display/util_test.py | 21 ++-- certbot/tests/eff_test.py | 18 ++-- certbot/tests/error_handler_test.py | 2 +- certbot/tests/helpful_test.py | 12 +-- certbot/tests/hook_test.py | 20 ++-- certbot/tests/lock_test.py | 14 +-- certbot/tests/log_test.py | 27 +++-- certbot/tests/main_test.py | 115 ++++++++++---------- certbot/tests/ocsp_test.py | 48 ++++----- certbot/tests/plugins/common_test.py | 6 +- certbot/tests/plugins/disco_test.py | 80 +++++++------- certbot/tests/plugins/dns_common_test.py | 12 +-- certbot/tests/plugins/manual_test.py | 9 +- certbot/tests/plugins/null_test.py | 2 +- certbot/tests/plugins/selection_test.py | 12 +-- certbot/tests/plugins/standalone_test.py | 11 +- certbot/tests/plugins/storage_test.py | 10 +- certbot/tests/plugins/util_test.py | 8 +- certbot/tests/plugins/webroot_test.py | 8 +- certbot/tests/renewal_test.py | 6 +- certbot/tests/renewupdater_test.py | 10 +- certbot/tests/reporter_test.py | 20 ++-- certbot/tests/reverter_test.py | 6 +- certbot/tests/storage_test.py | 34 +++--- certbot/tests/util_test.py | 18 ++-- 41 files changed, 444 insertions(+), 452 deletions(-) diff --git a/acme/tests/challenges_test.py b/acme/tests/challenges_test.py index cc604b0de..71bf61976 100644 --- a/acme/tests/challenges_test.py +++ b/acme/tests/challenges_test.py @@ -292,7 +292,7 @@ class TLSALPN01ResponseTest(unittest.TestCase): def test_gen_verify_cert_gen_key(self): cert, key = self.response.gen_cert(self.domain) - self.assertTrue(isinstance(key, OpenSSL.crypto.PKey)) + self.assertIsInstance(key, OpenSSL.crypto.PKey) self.assertTrue(self.response.verify_cert(self.domain, cert)) def test_verify_bad_cert(self): @@ -431,7 +431,7 @@ class DNSTest(unittest.TestCase): mock_gen.return_value = mock.sentinel.validation response = self.msg.gen_response(KEY) from acme.challenges import DNSResponse - self.assertTrue(isinstance(response, DNSResponse)) + self.assertIsInstance(response, DNSResponse) self.assertEqual(response.validation, mock.sentinel.validation) def test_validation_domain_name(self): diff --git a/acme/tests/client_test.py b/acme/tests/client_test.py index 89e66c6d6..35cc0ba25 100644 --- a/acme/tests/client_test.py +++ b/acme/tests/client_test.py @@ -604,8 +604,8 @@ class ClientTest(ClientTestBase): # make sure that max_attempts is per-authorization, rather # than global max_attempts=max(len(authzrs[0].retries), len(authzrs[1].retries))) - self.assertTrue(cert[0] is csr) - self.assertTrue(cert[1] is updated_authzrs) + self.assertIs(cert[0], csr) + self.assertIs(cert[1], updated_authzrs) self.assertEqual(updated_authzrs[0].uri, 'a...') self.assertEqual(updated_authzrs[1].uri, 'b.') self.assertEqual(updated_authzrs[0].times, [ @@ -641,7 +641,7 @@ class ClientTest(ClientTestBase): authzr = self.client.deactivate_authorization(self.authzr) self.assertEqual(authzb, authzr.body) self.assertEqual(self.client.net.post.call_count, 1) - self.assertTrue(self.authzr.uri in self.net.post.call_args_list[0][0]) + self.assertIn(self.authzr.uri, self.net.post.call_args_list[0][0]) def test_check_cert(self): self.response.headers['Location'] = self.certr.uri @@ -700,7 +700,7 @@ class ClientTest(ClientTestBase): def test_revocation_payload(self): obj = messages.Revocation(certificate=self.certr.body, reason=self.rsn) - self.assertTrue('reason' in obj.to_partial_json().keys()) + self.assertIn('reason', obj.to_partial_json().keys()) self.assertEqual(self.rsn, obj.to_partial_json()['reason']) def test_revoke_bad_status_raises_error(self): @@ -877,9 +877,9 @@ class ClientV2Test(ClientTestBase): self.response.headers['Location'] = self.regr.uri self.response.json.return_value = self.regr.body.to_json() self.assertEqual(self.regr, self.client.update_registration(self.regr)) - self.assertNotEqual(self.client.net.account, None) + self.assertIsNotNone(self.client.net.account) self.assertEqual(self.client.net.post.call_count, 2) - self.assertTrue(DIRECTORY_V2.newAccount in self.net.post.call_args_list[0][0]) + self.assertIn(DIRECTORY_V2.newAccount, self.net.post.call_args_list[0][0]) self.response.json.return_value = self.regr.body.update( contact=()).to_json() @@ -943,7 +943,7 @@ class ClientNetworkTest(unittest.TestCase): self.response.links = {} def test_init(self): - self.assertTrue(self.net.verify_ssl is self.verify_ssl) + self.assertIs(self.net.verify_ssl, self.verify_ssl) def test_wrap_in_jws(self): # pylint: disable=protected-access @@ -1185,7 +1185,7 @@ class ClientNetworkWithMockedResponseTest(unittest.TestCase): def send_request(*args, **kwargs): # pylint: disable=unused-argument,missing-docstring - self.assertFalse("new_nonce_url" in kwargs) + self.assertNotIn("new_nonce_url", kwargs) method = args[0] uri = args[1] if method == 'HEAD' and uri != "new_nonce_uri": @@ -1330,7 +1330,7 @@ class ClientNetworkSourceAddressBindingTest(unittest.TestCase): from acme.client import ClientNetwork net = ClientNetwork(key=None, alg=None, source_address=self.source_address) for adapter in net.session.adapters.values(): - self.assertTrue(self.source_address in adapter.source_address) + self.assertIn(self.source_address, adapter.source_address) def test_behavior_assumption(self): """This is a test that guardrails the HTTPAdapter behavior so that if the default for diff --git a/acme/tests/crypto_util_test.py b/acme/tests/crypto_util_test.py index 8c1f905d2..cc81a2f1f 100644 --- a/acme/tests/crypto_util_test.py +++ b/acme/tests/crypto_util_test.py @@ -191,7 +191,7 @@ class RandomSnTest(unittest.TestCase): for _ in range(self.cert_count): cert = gen_ss_cert(self.key, ['dummy'], force_san=True) self.serial_num.append(cert.get_serial_number()) - self.assertTrue(len(set(self.serial_num)) > 1) + self.assertGreater(len(set(self.serial_num)), 1) class MakeCSRTest(unittest.TestCase): """Test for standalone functions.""" @@ -206,8 +206,8 @@ class MakeCSRTest(unittest.TestCase): def test_make_csr(self): csr_pem = self._call_with_key(["a.example", "b.example"]) - self.assertTrue(b'--BEGIN CERTIFICATE REQUEST--' in csr_pem) - self.assertTrue(b'--END CERTIFICATE REQUEST--' in csr_pem) + self.assertIn(b'--BEGIN CERTIFICATE REQUEST--', csr_pem) + self.assertIn(b'--END CERTIFICATE REQUEST--', csr_pem) csr = OpenSSL.crypto.load_certificate_request( OpenSSL.crypto.FILETYPE_PEM, csr_pem) # In pyopenssl 0.13 (used with TOXENV=py27-oldest), csr objects don't diff --git a/acme/tests/errors_test.py b/acme/tests/errors_test.py index 11c57059c..f325b284e 100644 --- a/acme/tests/errors_test.py +++ b/acme/tests/errors_test.py @@ -24,8 +24,8 @@ class MissingNonceTest(unittest.TestCase): self.error = MissingNonce(self.response) def test_str(self): - self.assertTrue("FOO" in str(self.error)) - self.assertTrue("{}" in str(self.error)) + self.assertIn("FOO", str(self.error)) + self.assertIn("{}", str(self.error)) class PollErrorTest(unittest.TestCase): diff --git a/acme/tests/jws_test.py b/acme/tests/jws_test.py index 2e6ad72dd..0787fb340 100644 --- a/acme/tests/jws_test.py +++ b/acme/tests/jws_test.py @@ -48,7 +48,7 @@ class JWSTest(unittest.TestCase): self.assertEqual(jws.signature.combined.nonce, self.nonce) self.assertEqual(jws.signature.combined.url, self.url) self.assertEqual(jws.signature.combined.kid, self.kid) - self.assertEqual(jws.signature.combined.jwk, None) + self.assertIsNone(jws.signature.combined.jwk) # TODO: check that nonce is in protected header self.assertEqual(jws, JWS.from_json(jws.to_json())) @@ -58,7 +58,7 @@ class JWSTest(unittest.TestCase): jws = JWS.sign(payload=b'foo', key=self.privkey, alg=jose.RS256, nonce=self.nonce, url=self.url) - self.assertEqual(jws.signature.combined.kid, None) + self.assertIsNone(jws.signature.combined.kid) self.assertEqual(jws.signature.combined.jwk, self.pubkey) diff --git a/acme/tests/messages_test.py b/acme/tests/messages_test.py index 99a3a9ce4..3f0f29215 100644 --- a/acme/tests/messages_test.py +++ b/acme/tests/messages_test.py @@ -41,13 +41,13 @@ class ErrorTest(unittest.TestCase): def test_description(self): self.assertEqual('The request message was malformed', self.error.description) - self.assertTrue(self.error_custom.description is None) + self.assertIsNone(self.error_custom.description) def test_code(self): from acme.messages import Error self.assertEqual('malformed', self.error.code) - self.assertEqual(None, self.error_custom.code) - self.assertEqual(None, Error().code) + self.assertIsNone(self.error_custom.code) + self.assertIsNone(Error().code) def test_is_acme_error(self): from acme.messages import is_acme_error, Error @@ -260,10 +260,10 @@ class RegistrationTest(unittest.TestCase): self.assertEqual(empty_new_reg.contact, ()) self.assertEqual(new_reg_with_contact.contact, ()) - self.assertTrue('contact' not in empty_new_reg.to_partial_json()) - self.assertTrue('contact' not in empty_new_reg.fields_to_partial_json()) - self.assertTrue('contact' in new_reg_with_contact.to_partial_json()) - self.assertTrue('contact' in new_reg_with_contact.fields_to_partial_json()) + self.assertNotIn('contact', empty_new_reg.to_partial_json()) + self.assertNotIn('contact', empty_new_reg.fields_to_partial_json()) + self.assertIn('contact', new_reg_with_contact.to_partial_json()) + self.assertIn('contact', new_reg_with_contact.fields_to_partial_json()) class UpdateRegistrationTest(unittest.TestCase): @@ -406,7 +406,7 @@ class AuthorizationResourceTest(unittest.TestCase): authzr = AuthorizationResource( uri=mock.sentinel.uri, body=mock.sentinel.body) - self.assertTrue(isinstance(authzr, jose.JSONDeSerializable)) + self.assertIsInstance(authzr, jose.JSONDeSerializable) class CertificateRequestTest(unittest.TestCase): @@ -417,7 +417,7 @@ class CertificateRequestTest(unittest.TestCase): self.req = CertificateRequest(csr=CSR) def test_json_de_serializable(self): - self.assertTrue(isinstance(self.req, jose.JSONDeSerializable)) + self.assertIsInstance(self.req, jose.JSONDeSerializable) from acme.messages import CertificateRequest self.assertEqual( self.req, CertificateRequest.from_json(self.req.to_json())) @@ -433,7 +433,7 @@ class CertificateResourceTest(unittest.TestCase): cert_chain_uri=mock.sentinel.cert_chain_uri) def test_json_de_serializable(self): - self.assertTrue(isinstance(self.certr, jose.JSONDeSerializable)) + self.assertIsInstance(self.certr, jose.JSONDeSerializable) from acme.messages import CertificateResource self.assertEqual( self.certr, CertificateResource.from_json(self.certr.to_json())) diff --git a/certbot/tests/account_test.py b/certbot/tests/account_test.py index 7c8f52273..e034c5f32 100644 --- a/certbot/tests/account_test.py +++ b/certbot/tests/account_test.py @@ -150,7 +150,7 @@ class AccountFileStorageTest(test_util.ConfigTestCase): path = os.path.join(self.config.accounts_dir, self.acc.id, "regr.json") with open(path, "r") as f: regr = json.load(f) - self.assertTrue("new_authzr_uri" in regr) + self.assertIn("new_authzr_uri", regr) def test_update_regr(self): self.storage.update_regr(self.acc, self.mock_client) diff --git a/certbot/tests/auth_handler_test.py b/certbot/tests/auth_handler_test.py index 8eb5d7702..1f798c2d8 100644 --- a/certbot/tests/auth_handler_test.py +++ b/certbot/tests/auth_handler_test.py @@ -106,9 +106,9 @@ class HandleAuthorizationsTest(unittest.TestCase): self.assertEqual(mock_time.sleep.call_count, 2) # Retry-After header is 30 seconds, but at the time sleep is invoked, several # instructions are executed, and next pool is in less than 30 seconds. - self.assertTrue(mock_time.sleep.call_args_list[1][0][0] <= 30) + self.assertLessEqual(mock_time.sleep.call_args_list[1][0][0], 30) # However, assert that we did not took the default value of 3 seconds. - self.assertTrue(mock_time.sleep.call_args_list[1][0][0] > 3) + self.assertGreater(mock_time.sleep.call_args_list[1][0][0], 3) self.assertEqual(self.mock_auth.cleanup.call_count, 1) # Test if list first element is http-01, use typ because it is an achall @@ -139,7 +139,7 @@ class HandleAuthorizationsTest(unittest.TestCase): self.assertEqual(self.mock_auth.cleanup.call_count, 1) # Test if list first element is http-01, use typ because it is an achall for achall in self.mock_auth.cleanup.call_args[0][0]: - self.assertTrue(achall.typ in ["http-01", "dns-01"]) + self.assertIn(achall.typ, ["http-01", "dns-01"]) # Length of authorizations list self.assertEqual(len(authzr), 1) @@ -225,7 +225,7 @@ class HandleAuthorizationsTest(unittest.TestCase): with self.assertRaises(errors.AuthorizationError) as error: # We retry only once, so retries will be exhausted before STATUS_VALID is returned. self.handler.handle_authorizations(mock_order, False, 1) - self.assertTrue('All authorizations were not finalized by the CA.' in str(error.exception)) + self.assertIn('All authorizations were not finalized by the CA.', str(error.exception)) def test_no_domains(self): mock_order = mock.MagicMock(authorizations=[]) @@ -305,7 +305,7 @@ class HandleAuthorizationsTest(unittest.TestCase): with test_util.patch_get_utility(): with self.assertRaises(errors.AuthorizationError) as error: self.handler.handle_authorizations(mock_order, False) - self.assertTrue('Some challenges have failed.' in str(error.exception)) + self.assertIn('Some challenges have failed.', str(error.exception)) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual( self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01") @@ -341,7 +341,7 @@ class HandleAuthorizationsTest(unittest.TestCase): self.handler.handle_authorizations(mock_order, True) # Despite best_effort=True, process will fail because no authzr is valid. - self.assertTrue('All challenges have failed.' in str(error.exception)) + self.assertIn('All challenges have failed.', str(error.exception)) def test_validated_challenge_not_rerun(self): # With a pending challenge that is not supported by the plugin, we @@ -486,7 +486,7 @@ class ReportFailedAuthzrsTest(unittest.TestCase): } # Prevent future regressions if the error type changes - self.assertTrue(kwargs["error"].description is not None) + self.assertIsNotNone(kwargs["error"].description) http_01 = messages.ChallengeBody(**kwargs) @@ -511,7 +511,7 @@ class ReportFailedAuthzrsTest(unittest.TestCase): auth_handler._report_failed_authzrs([self.authzr1], 'key') call_list = mock_zope().add_message.call_args_list self.assertEqual(len(call_list), 1) - self.assertTrue("Domain: example.com\nType: tls\nDetail: detail" in call_list[0][0][0]) + self.assertIn("Domain: example.com\nType: tls\nDetail: detail", call_list[0][0][0]) @test_util.patch_get_utility() def test_different_errors_and_domains(self, mock_zope): diff --git a/certbot/tests/cert_manager_test.py b/certbot/tests/cert_manager_test.py index 918459256..3e8fb0de7 100644 --- a/certbot/tests/cert_manager_test.py +++ b/certbot/tests/cert_manager_test.py @@ -211,7 +211,7 @@ class CertificatesTest(BaseCertManagerTest): def test_certificates_quiet(self, mock_utility, mock_logger): self.config.quiet = True self._certificates(self.config) - self.assertFalse(mock_utility.notification.called) + self.assertIs(mock_utility.notification.called, False) self.assertTrue(mock_logger.warning.called) #pylint: disable=no-member @mock.patch('certbot.crypto_util.verify_renewable_cert') @@ -224,7 +224,7 @@ class CertificatesTest(BaseCertManagerTest): mock_verifier.return_value = None mock_report.return_value = "" self._certificates(self.config) - self.assertFalse(mock_logger.warning.called) + self.assertIs(mock_logger.warning.called, False) self.assertTrue(mock_report.called) self.assertTrue(mock_utility.called) self.assertTrue(mock_renewable_cert.called) @@ -242,7 +242,7 @@ class CertificatesTest(BaseCertManagerTest): filesystem.makedirs(empty_config.renewal_configs_dir) self._certificates(empty_config) - self.assertFalse(mock_logger.warning.called) + self.assertIs(mock_logger.warning.called, False) self.assertTrue(mock_utility.called) shutil.rmtree(empty_tempdir) @@ -269,31 +269,34 @@ class CertificatesTest(BaseCertManagerTest): get_report = lambda: cert_manager._report_human_readable(mock_config, parsed_certs) out = get_report() - self.assertTrue("INVALID: EXPIRED" in out) + self.assertIn("INVALID: EXPIRED", out) cert.target_expiry += datetime.timedelta(hours=2) # pylint: disable=protected-access out = get_report() - self.assertTrue('1 hour(s)' in out or '2 hour(s)' in out) - self.assertTrue('VALID' in out and 'INVALID' not in out) + self.assertIs('1 hour' in out or '2 hour(s)' in out, True) + self.assertIn('VALID', out) + self.assertNotIn('INVALID', out) cert.target_expiry += datetime.timedelta(days=1) # pylint: disable=protected-access out = get_report() - self.assertTrue('1 day' in out) - self.assertFalse('under' in out) - self.assertTrue('VALID' in out and 'INVALID' not in out) + self.assertIn('1 day', out) + self.assertNotIn('under', out) + self.assertIn('VALID', out) + self.assertNotIn('INVALID', out) cert.target_expiry += datetime.timedelta(days=2) # pylint: disable=protected-access out = get_report() - self.assertTrue('3 days' in out) - self.assertTrue('VALID' in out and 'INVALID' not in out) + self.assertIn('3 days', out) + self.assertIn('VALID', out) + self.assertNotIn('INVALID', out) cert.is_test_cert = True mock_revoked.return_value = True out = get_report() - self.assertTrue('INVALID: TEST_CERT, REVOKED' in out) + self.assertIn('INVALID: TEST_CERT, REVOKED', out) cert = mock.MagicMock(lineagename="indescribable") cert.target_expiry = expiry @@ -353,7 +356,7 @@ class LineageForCertnameTest(BaseCertManagerTest): def test_no_match(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.return_value = "other.com.conf" from certbot._internal import cert_manager - self.assertEqual(cert_manager.lineage_for_certname(self.config, "example.com"), None) + self.assertIsNone(cert_manager.lineage_for_certname(self.config, "example.com")) self.assertTrue(mock_make_or_verify_dir.called) @mock.patch('certbot.util.make_or_verify_dir') @@ -361,7 +364,7 @@ class LineageForCertnameTest(BaseCertManagerTest): def test_no_renewal_file(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.side_effect = errors.CertStorageError() from certbot._internal import cert_manager - self.assertEqual(cert_manager.lineage_for_certname(self.config, "example.com"), None) + self.assertIsNone(cert_manager.lineage_for_certname(self.config, "example.com")) self.assertTrue(mock_make_or_verify_dir.called) @@ -388,7 +391,7 @@ class DomainsForCertnameTest(BaseCertManagerTest): def test_no_match(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.return_value = "somefile.conf" from certbot._internal import cert_manager - self.assertEqual(cert_manager.domains_for_certname(self.config, "other.com"), None) + self.assertIsNone(cert_manager.domains_for_certname(self.config, "other.com")) self.assertTrue(mock_make_or_verify_dir.called) @@ -450,7 +453,7 @@ class RenameLineageTest(BaseCertManagerTest): self._call(self.config) from certbot._internal import cert_manager updated_lineage = cert_manager.lineage_for_certname(self.config, self.config.new_certname) - self.assertTrue(updated_lineage is not None) + self.assertIsNotNone(updated_lineage) self.assertEqual(updated_lineage.lineagename, self.config.new_certname) @test_util.patch_get_utility() @@ -463,7 +466,7 @@ class RenameLineageTest(BaseCertManagerTest): self._call(self.config) from certbot._internal import cert_manager updated_lineage = cert_manager.lineage_for_certname(self.config, self.config.new_certname) - self.assertTrue(updated_lineage is not None) + self.assertIsNotNone(updated_lineage) self.assertEqual(updated_lineage.lineagename, self.config.new_certname) @test_util.patch_get_utility() @@ -503,12 +506,12 @@ class DuplicativeCertsTest(storage_test.BaseRenewableCertTest): result = find_duplicative_certs( self.config, ['example.com', 'www.example.com']) self.assertTrue(result[0].configfile.filename.endswith('example.org.conf')) - self.assertEqual(result[1], None) + self.assertIsNone(result[1]) # Superset result = find_duplicative_certs( self.config, ['example.com', 'www.example.com', 'something.new']) - self.assertEqual(result[0], None) + self.assertIsNone(result[0]) self.assertTrue(result[1].configfile.filename.endswith('example.org.conf')) # Partial overlap doesn't count @@ -629,8 +632,7 @@ class GetCertnameTest(unittest.TestCase): self.assertEqual( cert_manager.get_certnames( self.config, "verb", allow_multiple=False), ['example.com']) - self.assertTrue( - prompt in self.mock_get_utility().menu.call_args[0][0]) + self.assertIn(prompt, self.mock_get_utility().menu.call_args[0][0]) @mock.patch('certbot._internal.storage.renewal_conf_files') @mock.patch('certbot._internal.storage.lineagename_for_filename') @@ -671,8 +673,7 @@ class GetCertnameTest(unittest.TestCase): self.assertEqual( cert_manager.get_certnames( self.config, "verb", allow_multiple=True), ['example.com']) - self.assertTrue( - prompt in self.mock_get_utility().checklist.call_args[0][0]) + self.assertIn(prompt, self.mock_get_utility().checklist.call_args[0][0]) @mock.patch('certbot._internal.storage.renewal_conf_files') @mock.patch('certbot._internal.storage.lineagename_for_filename') diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py index 0a0d2634a..8cab7a5b1 100644 --- a/certbot/tests/cli_test.py +++ b/certbot/tests/cli_test.py @@ -150,79 +150,79 @@ class ParseTest(unittest.TestCase): def test_help(self): self._help_output(['--help']) # assert SystemExit is raised here out = self._help_output(['--help', 'all']) - self.assertTrue("--configurator" in out) - self.assertTrue("how a certificate is deployed" in out) - self.assertTrue("--webroot-path" in out) - self.assertTrue("--text" not in out) - self.assertTrue("%s" not in out) - self.assertTrue("{0}" not in out) - self.assertTrue("--renew-hook" not in out) + self.assertIn("--configurator", out) + self.assertIn("how a certificate is deployed", out) + self.assertIn("--webroot-path", out) + self.assertNotIn("--text", out) + self.assertNotIn("%s", out) + self.assertNotIn("{0}", out) + self.assertNotIn("--renew-hook", out) out = self._help_output(['-h', 'nginx']) if "nginx" in PLUGINS: # may be false while building distributions without plugins - self.assertTrue("--nginx-ctl" in out) - self.assertTrue("--webroot-path" not in out) - self.assertTrue("--checkpoints" not in out) + self.assertIn("--nginx-ctl", out) + self.assertNotIn("--webroot-path", out) + self.assertNotIn("--checkpoints", out) out = self._help_output(['-h']) if "nginx" in PLUGINS: - self.assertTrue("Use the Nginx plugin" in out) + self.assertIn("Use the Nginx plugin", out) else: - self.assertTrue("(the certbot nginx plugin is not" in out) + self.assertIn("(the certbot nginx plugin is not", out) out = self._help_output(['--help', 'plugins']) - self.assertTrue("--webroot-path" not in out) - self.assertTrue("--prepare" in out) - self.assertTrue('"plugins" subcommand' in out) + self.assertNotIn("--webroot-path", out) + self.assertIn("--prepare", out) + self.assertIn('"plugins" subcommand', out) # test multiple topics out = self._help_output(['-h', 'renew']) - self.assertTrue("--keep" in out) + self.assertIn("--keep", out) out = self._help_output(['-h', 'automation']) - self.assertTrue("--keep" in out) + self.assertIn("--keep", out) out = self._help_output(['-h', 'revoke']) - self.assertTrue("--keep" not in out) + self.assertNotIn("--keep", out) out = self._help_output(['--help', 'install']) - self.assertTrue("--cert-path" in out) - self.assertTrue("--key-path" in out) + self.assertIn("--cert-path", out) + self.assertIn("--key-path", out) out = self._help_output(['--help', 'revoke']) - self.assertTrue("--cert-path" in out) - self.assertTrue("--key-path" in out) - self.assertTrue("--reason" in out) - self.assertTrue("--delete-after-revoke" in out) - self.assertTrue("--no-delete-after-revoke" in out) + self.assertIn("--cert-path", out) + self.assertIn("--key-path", out) + self.assertIn("--reason", out) + self.assertIn("--delete-after-revoke", out) + self.assertIn("--no-delete-after-revoke", out) out = self._help_output(['-h', 'register']) - self.assertTrue("--cert-path" not in out) - self.assertTrue("--key-path" not in out) + self.assertNotIn("--cert-path", out) + self.assertNotIn("--key-path", out) out = self._help_output(['-h']) - self.assertTrue(cli.SHORT_USAGE in out) - self.assertTrue(cli.COMMAND_OVERVIEW[:100] in out) - self.assertTrue("%s" not in out) - self.assertTrue("{0}" not in out) + self.assertIn(cli.SHORT_USAGE, out) + self.assertIn(cli.COMMAND_OVERVIEW[:100], out) + self.assertNotIn("%s", out) + self.assertNotIn("{0}", out) def test_help_no_dashes(self): self._help_output(['help']) # assert SystemExit is raised here out = self._help_output(['help', 'all']) - self.assertTrue("--configurator" in out) - self.assertTrue("how a certificate is deployed" in out) - self.assertTrue("--webroot-path" in out) - self.assertTrue("--text" not in out) - self.assertTrue("%s" not in out) - self.assertTrue("{0}" not in out) + self.assertIn("--configurator", out) + self.assertIn("how a certificate is deployed", out) + self.assertIn("--webroot-path", out) + self.assertNotIn("--text", out) + self.assertNotIn("%s", out) + self.assertNotIn("{0}", out) out = self._help_output(['help', 'install']) - self.assertTrue("--cert-path" in out) - self.assertTrue("--key-path" in out) + self.assertIn("--cert-path", out) + self.assertIn("--key-path", out) out = self._help_output(['help', 'revoke']) - self.assertTrue("--cert-path" in out) - self.assertTrue("--key-path" in out) + self.assertIn("--cert-path", out) + self.assertIn("--key-path", out) def test_parse_domains(self): short_args = ['-d', 'example.com'] @@ -270,8 +270,8 @@ class ParseTest(unittest.TestCase): def test_must_staple_flag(self): short_args = ['--must-staple'] namespace = self.parse(short_args) - self.assertTrue(namespace.must_staple) - self.assertTrue(namespace.staple) + self.assertIs(namespace.must_staple, True) + self.assertIs(namespace.staple, True) def _check_server_conflict_message(self, parser_args, conflicting_args): try: @@ -280,31 +280,31 @@ class ParseTest(unittest.TestCase): "The following flags didn't conflict with " '--server: {0}'.format(', '.join(conflicting_args))) except errors.Error as error: - self.assertTrue('--server' in str(error)) + self.assertIn('--server', str(error)) for arg in conflicting_args: - self.assertTrue(arg in str(error)) + self.assertIn(arg, str(error)) def test_staging_flag(self): short_args = ['--staging'] namespace = self.parse(short_args) - self.assertTrue(namespace.staging) + self.assertIs(namespace.staging, True) self.assertEqual(namespace.server, constants.STAGING_URI) short_args += '--server example.com'.split() self._check_server_conflict_message(short_args, '--staging') def _assert_dry_run_flag_worked(self, namespace, existing_account): - self.assertTrue(namespace.dry_run) - self.assertTrue(namespace.break_my_certs) - self.assertTrue(namespace.staging) + self.assertIs(namespace.dry_run, True) + self.assertIs(namespace.break_my_certs, True) + self.assertIs(namespace.staging, True) self.assertEqual(namespace.server, constants.STAGING_URI) if existing_account: - self.assertTrue(namespace.tos) - self.assertTrue(namespace.register_unsafely_without_email) + self.assertIs(namespace.tos, True) + self.assertIs(namespace.register_unsafely_without_email, True) else: - self.assertFalse(namespace.tos) - self.assertFalse(namespace.register_unsafely_without_email) + self.assertIs(namespace.tos, False) + self.assertIs(namespace.register_unsafely_without_email, False) def test_dry_run_flag(self): config_dir = tempfile.mkdtemp() @@ -350,8 +350,8 @@ class ParseTest(unittest.TestCase): key_size_value = cli.flag_default(key_size_option) self.parse('--rsa-key-size {0}'.format(key_size_value).split()) - self.assertTrue(cli.option_was_set(key_size_option, key_size_value)) - self.assertTrue(cli.option_was_set('no_verify_ssl', True)) + self.assertIs(cli.option_was_set(key_size_option, key_size_value), True) + self.assertIs(cli.option_was_set('no_verify_ssl', True), True) config_dir_option = 'config_dir' self.assertFalse(cli.option_was_set( @@ -425,7 +425,7 @@ class ParseTest(unittest.TestCase): value = "foo" namespace = self.parse( ["--renew-hook", value, "--disable-hook-validation"]) - self.assertEqual(namespace.deploy_hook, None) + self.assertIsNone(namespace.deploy_hook) self.assertEqual(namespace.renew_hook, value) def test_max_log_backups_error(self): @@ -456,19 +456,19 @@ class ParseTest(unittest.TestCase): self.assertFalse(self.parse(["--no-directory-hooks"]).directory_hooks) def test_no_directory_hooks_unset(self): - self.assertTrue(self.parse([]).directory_hooks) + self.assertIs(self.parse([]).directory_hooks, True) def test_delete_after_revoke(self): namespace = self.parse(["--delete-after-revoke"]) - self.assertTrue(namespace.delete_after_revoke) + self.assertIs(namespace.delete_after_revoke, True) def test_delete_after_revoke_default(self): namespace = self.parse([]) - self.assertEqual(namespace.delete_after_revoke, None) + self.assertIsNone(namespace.delete_after_revoke) def test_no_delete_after_revoke(self): namespace = self.parse(["--no-delete-after-revoke"]) - self.assertFalse(namespace.delete_after_revoke) + self.assertIs(namespace.delete_after_revoke, False) def test_allow_subset_with_wildcard(self): self.assertRaises(errors.Error, self.parse, @@ -477,7 +477,7 @@ class ParseTest(unittest.TestCase): def test_route53_no_revert(self): for help_flag in ['-h', '--help']: for topic in ['all', 'plugins', 'dns-route53']: - self.assertFalse('certbot-route53:auth' in self._help_output([help_flag, topic])) + self.assertNotIn('certbot-route53:auth', self._help_output([help_flag, topic])) class DefaultTest(unittest.TestCase): @@ -490,8 +490,8 @@ class DefaultTest(unittest.TestCase): self.default2 = cli._Default() def test_boolean(self): - self.assertFalse(self.default1) - self.assertFalse(self.default2) + self.assertIs(bool(self.default1), False) + self.assertIs(bool(self.default2), False) def test_equality(self): self.assertEqual(self.default1, self.default2) @@ -514,7 +514,7 @@ class SetByCliTest(unittest.TestCase): def test_webroot_map(self): args = '-w /var/www/html -d example.com'.split() verb = 'renew' - self.assertTrue(_call_set_by_cli('webroot_map', args, verb)) + self.assertIs(_call_set_by_cli('webroot_map', args, verb), True) def _call_set_by_cli(var, args, verb): diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py index 1d88ea84c..a89636a63 100644 --- a/certbot/tests/client_test.py +++ b/certbot/tests/client_test.py @@ -93,11 +93,11 @@ class RegisterTest(test_util.ConfigTestCase): with mock.patch("certbot._internal.eff.prepare_subscription") as mock_prepare: mock_client().new_account_and_tos.side_effect = errors.Error self.assertRaises(errors.Error, self._call) - self.assertFalse(mock_prepare.called) + self.assertIs(mock_prepare.called, False) mock_client().new_account_and_tos.side_effect = None self._call() - self.assertTrue(mock_prepare.called) + self.assertIs(mock_prepare.called, True) def test_it(self): with mock.patch("certbot._internal.client.acme_client.BackwardsCompatibleClientV2") as mock_client: @@ -117,7 +117,7 @@ class RegisterTest(test_util.ConfigTestCase): mock_client().new_account_and_tos.side_effect = [mx_err, mock.MagicMock()] self._call() self.assertEqual(mock_get_email.call_count, 1) - self.assertTrue(mock_prepare.called) + self.assertIs(mock_prepare.called, True) def test_email_invalid_noninteractive(self): from acme import messages @@ -144,7 +144,7 @@ class RegisterTest(test_util.ConfigTestCase): self.config.dry_run = False self._call() mock_logger.debug.assert_called_once_with(mock.ANY) - self.assertTrue(mock_prepare.called) + self.assertIs(mock_prepare.called, True) @mock.patch("certbot._internal.client.display_ops.get_email") def test_dry_run_no_staging_account(self, mock_get_email): @@ -155,7 +155,7 @@ class RegisterTest(test_util.ConfigTestCase): self.config.dry_run = True self._call() # check Certbot did not ask the user to provide an email - self.assertFalse(mock_get_email.called) + self.assertIs(mock_get_email.called, False) # check Certbot created an account with no email. Contact should return empty self.assertFalse(mock_client().new_account_and_tos.call_args[0][0].contact) @@ -172,7 +172,7 @@ class RegisterTest(test_util.ConfigTestCase): self.config.eab_hmac_key = "J2OAqW4MHXsrHVa_PVg0Y-L_R4SYw0_aL1le6mfblbE" self._call() - self.assertTrue(mock_eab_from_data.called) + self.assertIs(mock_eab_from_data.called, True) def test_without_eab_arguments(self): with mock.patch("certbot._internal.client.acme_client.BackwardsCompatibleClientV2") as mock_client: @@ -184,7 +184,7 @@ class RegisterTest(test_util.ConfigTestCase): self.config.eab_hmac_key = None self._call() - self.assertFalse(mock_eab_from_data.called) + self.assertIs(mock_eab_from_data.called, False) def test_external_account_required_without_eab_arguments(self): with mock.patch("certbot._internal.client.acme_client.BackwardsCompatibleClientV2") as mock_client: @@ -209,7 +209,7 @@ class RegisterTest(test_util.ConfigTestCase): with mock.patch("certbot._internal.eff.handle_subscription") as mock_handle: mock_client().new_account_and_tos.side_effect = [mx_err, mock.MagicMock()] self.assertRaises(messages.Error, self._call) - self.assertFalse(mock_handle.called) + self.assertIs(mock_handle.called, False) class ClientTestCommon(test_util.ConfigTestCase): @@ -246,7 +246,7 @@ class ClientTest(ClientTestCommon): def test_init_acme_verify_ssl(self): net = self.acme_client.call_args[0][0] - self.assertTrue(net.verify_ssl) + self.assertIs(net.verify_ssl, True) def _mock_obtain_certificate(self): self.client.auth_handler = mock.MagicMock() @@ -608,7 +608,7 @@ class EnhanceConfigTest(ClientTestCommon): def test_already_exists_header(self, mock_log): self.config.hsts = True self._test_with_already_existing() - self.assertTrue(mock_log.warning.called) + self.assertIs(mock_log.warning.called, True) self.assertEqual(mock_log.warning.call_args[0][1], 'Strict-Transport-Security') @@ -616,7 +616,7 @@ class EnhanceConfigTest(ClientTestCommon): def test_already_exists_redirect(self, mock_log): self.config.redirect = True self._test_with_already_existing() - self.assertTrue(mock_log.warning.called) + self.assertIs(mock_log.warning.called, True) self.assertEqual(mock_log.warning.call_args[0][1], 'redirect') @@ -624,13 +624,13 @@ class EnhanceConfigTest(ClientTestCommon): def test_config_set_no_warning_redirect(self, mock_log): self.config.redirect = False self._test_with_already_existing() - self.assertFalse(mock_log.warning.called) + self.assertIs(mock_log.warning.called, False) @mock.patch("certbot._internal.client.logger") def test_no_warn_redirect(self, mock_log): self.config.redirect = None self._test_with_all_supported() - self.assertFalse(mock_log.warning.called) + self.assertIs(mock_log.warning.called, False) def test_no_ask_hsts(self): self.config.hsts = True @@ -683,7 +683,7 @@ class EnhanceConfigTest(ClientTestCommon): def _test_error_with_rollback(self): self._test_error() - self.assertTrue(self.client.installer.restart.called) + self.assertIs(self.client.installer.restart.called, True) def _test_error(self): self.config.redirect = True diff --git a/certbot/tests/compat/filesystem_test.py b/certbot/tests/compat/filesystem_test.py index 47da2b415..9aab49c34 100644 --- a/certbot/tests/compat/filesystem_test.py +++ b/certbot/tests/compat/filesystem_test.py @@ -157,17 +157,17 @@ class UmaskTest(TempDirTestCase): try: dir1 = os.path.join(self.tempdir, 'probe1') filesystem.mkdir(dir1) - self.assertTrue(filesystem.check_mode(dir1, 0o755)) + self.assertIs(filesystem.check_mode(dir1, 0o755), True) filesystem.umask(0o077) dir2 = os.path.join(self.tempdir, 'dir2') filesystem.mkdir(dir2) - self.assertTrue(filesystem.check_mode(dir2, 0o700)) + self.assertIs(filesystem.check_mode(dir2, 0o700), True) dir3 = os.path.join(self.tempdir, 'dir3') filesystem.mkdir(dir3, mode=0o777) - self.assertTrue(filesystem.check_mode(dir3, 0o700)) + self.assertIs(filesystem.check_mode(dir3, 0o700), True) finally: filesystem.umask(previous_umask) @@ -177,17 +177,17 @@ class UmaskTest(TempDirTestCase): try: file1 = os.path.join(self.tempdir, 'probe1') UmaskTest._create_file(file1) - self.assertTrue(filesystem.check_mode(file1, 0o755)) + self.assertIs(filesystem.check_mode(file1, 0o755), True) filesystem.umask(0o077) file2 = os.path.join(self.tempdir, 'probe2') UmaskTest._create_file(file2) - self.assertTrue(filesystem.check_mode(file2, 0o700)) + self.assertIs(filesystem.check_mode(file2, 0o700), True) file3 = os.path.join(self.tempdir, 'probe3') UmaskTest._create_file(file3) - self.assertTrue(filesystem.check_mode(file3, 0o700)) + self.assertIs(filesystem.check_mode(file3, 0o700), True) finally: filesystem.umask(previous_umask) @@ -400,7 +400,7 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): util.safe_open(path1, 'w').close() util.safe_open(path2, 'w').close() - self.assertTrue(filesystem.has_same_ownership(path1, path2)) + self.assertIs(filesystem.has_same_ownership(path1, path2), True) @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') def test_copy_ownership_and_mode_windows(self): @@ -408,8 +408,8 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): dst = _create_probe(self.tempdir, name='dst') filesystem.chmod(src, 0o700) - self.assertTrue(filesystem.check_mode(src, 0o700)) - self.assertTrue(filesystem.check_mode(dst, 0o744)) + self.assertIs(filesystem.check_mode(src, 0o700), True) + self.assertIs(filesystem.check_mode(dst, 0o744), True) # Checking an actual change of owner is tricky during a unit test, since we do not know # if any user exists beside the current one. So we mock _copy_win_ownership. It's behavior @@ -418,7 +418,7 @@ class CopyOwnershipAndModeTest(test_util.TempDirTestCase): filesystem.copy_ownership_and_mode(src, dst) mock_copy_owner.assert_called_once_with(src, dst) - self.assertTrue(filesystem.check_mode(dst, 0o700)) + self.assertIs(filesystem.check_mode(dst, 0o700), True) class CheckPermissionsTest(test_util.TempDirTestCase): @@ -428,14 +428,14 @@ class CheckPermissionsTest(test_util.TempDirTestCase): self.probe_path = _create_probe(self.tempdir) def test_check_mode(self): - self.assertTrue(filesystem.check_mode(self.probe_path, 0o744)) + self.assertIs(filesystem.check_mode(self.probe_path, 0o744), True) filesystem.chmod(self.probe_path, 0o700) self.assertFalse(filesystem.check_mode(self.probe_path, 0o744)) @unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security') def test_check_owner_windows(self): - self.assertTrue(filesystem.check_owner(self.probe_path)) + self.assertIs(filesystem.check_owner(self.probe_path), True) system = win32security.ConvertStringSidToSid(SYSTEM_SID) security = win32security.SECURITY_ATTRIBUTES().SECURITY_DESCRIPTOR @@ -447,7 +447,7 @@ class CheckPermissionsTest(test_util.TempDirTestCase): @unittest.skipUnless(POSIX_MODE, reason='Test specific to Linux security') def test_check_owner_linux(self): - self.assertTrue(filesystem.check_owner(self.probe_path)) + self.assertIs(filesystem.check_owner(self.probe_path), True) import os as std_os # pylint: disable=os-module-forbidden # See related inline comment in certbot.compat.filesystem.check_owner method @@ -459,7 +459,7 @@ class CheckPermissionsTest(test_util.TempDirTestCase): self.assertFalse(filesystem.check_owner(self.probe_path)) def test_check_permissions(self): - self.assertTrue(filesystem.check_permissions(self.probe_path, 0o744)) + self.assertIs(filesystem.check_permissions(self.probe_path, 0o744), True) with mock.patch('certbot.compat.filesystem.check_mode') as mock_mode: mock_mode.return_value = False @@ -471,7 +471,7 @@ class CheckPermissionsTest(test_util.TempDirTestCase): def test_check_min_permissions(self): filesystem.chmod(self.probe_path, 0o744) - self.assertTrue(filesystem.has_min_permissions(self.probe_path, 0o744)) + self.assertIs(filesystem.has_min_permissions(self.probe_path, 0o744), True) filesystem.chmod(self.probe_path, 0o700) self.assertFalse(filesystem.has_min_permissions(self.probe_path, 0o744)) @@ -481,7 +481,7 @@ class CheckPermissionsTest(test_util.TempDirTestCase): def test_is_world_reachable(self): filesystem.chmod(self.probe_path, 0o744) - self.assertTrue(filesystem.has_world_permissions(self.probe_path)) + self.assertIs(filesystem.has_world_permissions(self.probe_path), True) filesystem.chmod(self.probe_path, 0o700) self.assertFalse(filesystem.has_world_permissions(self.probe_path)) @@ -500,7 +500,7 @@ class OsReplaceTest(test_util.TempDirTestCase): filesystem.replace(src, dst) self.assertFalse(os.path.exists(src)) - self.assertTrue(os.path.exists(dst)) + self.assertIs(os.path.exists(dst), True) class RealpathTest(test_util.TempDirTestCase): @@ -542,7 +542,7 @@ class RealpathTest(test_util.TempDirTestCase): with self.assertRaises(RuntimeError) as error: filesystem.realpath(link1_path) - self.assertTrue('link1 is a loop!' in str(error.exception)) + self.assertIn('link1 is a loop!', str(error.exception)) class IsExecutableTest(test_util.TempDirTestCase): @@ -578,7 +578,7 @@ class IsExecutableTest(test_util.TempDirTestCase): with _fix_windows_runtime(): mock_access.return_value = True mock_isfile.return_value = True - self.assertTrue(filesystem.is_executable("/path/to/exe")) + self.assertIs(filesystem.is_executable("/path/to/exe"), True) @mock.patch("certbot.compat.filesystem.os.path.isfile") @mock.patch("certbot.compat.filesystem.os.access") @@ -586,7 +586,7 @@ class IsExecutableTest(test_util.TempDirTestCase): with _fix_windows_runtime(): mock_access.return_value = True mock_isfile.return_value = True - self.assertTrue(filesystem.is_executable("exe")) + self.assertIs(filesystem.is_executable("exe"), True) @mock.patch("certbot.compat.filesystem.os.path.isfile") @mock.patch("certbot.compat.filesystem.os.access") diff --git a/certbot/tests/compat/misc_test.py b/certbot/tests/compat/misc_test.py index 642f395ba..e87498cbe 100644 --- a/certbot/tests/compat/misc_test.py +++ b/certbot/tests/compat/misc_test.py @@ -45,4 +45,4 @@ class ExecuteTest(unittest.TestCase): mock_logger.info.assert_any_call(mock.ANY, mock.ANY, mock.ANY, stdout) if stderr or returncode: - self.assertTrue(mock_logger.error.called) + self.assertIs(mock_logger.error.called, True) diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py index a2b89ee17..432fdbe53 100644 --- a/certbot/tests/crypto_util_test.py +++ b/certbot/tests/crypto_util_test.py @@ -60,7 +60,7 @@ class InitSaveKeyTest(test_util.TempDirTestCase): mock_make.return_value = b'key_pem' key = self._call(1024, self.workdir) self.assertEqual(key.pem, b'key_pem') - self.assertTrue('key-certbot.pem' in key.file) + self.assertIn('key-certbot.pem', key.file) self.assertTrue(os.path.exists(os.path.join(self.workdir, key.file))) @mock.patch('certbot.crypto_util.make_key') @@ -89,7 +89,7 @@ class InitSaveCSRTest(test_util.TempDirTestCase): mock.Mock(pem='dummy_key'), 'example.com', self.tempdir) self.assertEqual(csr.data, b'csr_pem') - self.assertTrue('csr-certbot.pem' in csr.file) + self.assertIn('csr-certbot.pem', csr.file) class ValidCSRTest(unittest.TestCase): @@ -251,7 +251,7 @@ class VerifyRenewableCertTest(VerifyCertSetup): return verify_renewable_cert(renewable_cert) def test_verify_renewable_cert(self): - self.assertEqual(None, self._call(self.renewable_cert)) + self.assertIsNone(self._call(self.renewable_cert)) @mock.patch('certbot.crypto_util.verify_renewable_cert_sig', side_effect=errors.Error("")) def test_verify_renewable_cert_failure(self, unused_verify_renewable_cert_sign): @@ -266,14 +266,14 @@ class VerifyRenewableCertSigTest(VerifyCertSetup): return verify_renewable_cert_sig(renewable_cert) def test_cert_sig_match(self): - self.assertEqual(None, self._call(self.renewable_cert)) + self.assertIsNone(self._call(self.renewable_cert)) def test_cert_sig_match_ec(self): renewable_cert = mock.MagicMock() renewable_cert.cert_path = P256_CERT_PATH renewable_cert.chain_path = P256_CERT_PATH renewable_cert.key_path = P256_KEY - self.assertEqual(None, self._call(renewable_cert)) + self.assertIsNone(self._call(renewable_cert)) def test_cert_sig_mismatch(self): self.bad_renewable_cert.cert_path = test_util.vector_path('cert_512_bad.pem') @@ -288,7 +288,7 @@ class VerifyFullchainTest(VerifyCertSetup): return verify_fullchain(renewable_cert) def test_fullchain_matches(self): - self.assertEqual(None, self._call(self.renewable_cert)) + self.assertIsNone(self._call(self.renewable_cert)) def test_fullchain_mismatch(self): self.assertRaises(errors.Error, self._call, self.bad_renewable_cert) @@ -308,7 +308,7 @@ class VerifyCertMatchesPrivKeyTest(VerifyCertSetup): def test_cert_priv_key_match(self): self.renewable_cert.cert = SS_CERT_PATH self.renewable_cert.privkey = RSA2048_KEY_PATH - self.assertEqual(None, self._call(self.renewable_cert)) + self.assertIsNone(self._call(self.renewable_cert)) def test_cert_priv_key_mismatch(self): self.bad_renewable_cert.privkey = RSA256_KEY_PATH diff --git a/certbot/tests/display/completer_test.py b/certbot/tests/display/completer_test.py index 087617310..75b11d1d7 100644 --- a/certbot/tests/display/completer_test.py +++ b/certbot/tests/display/completer_test.py @@ -50,12 +50,12 @@ class CompleterTest(test_util.TempDirTestCase): for i in range(num_paths): completion = my_completer.complete(self.tempdir, i) - self.assertTrue(completion in self.paths) + self.assertIn(completion, self.paths) self.paths.remove(completion) - self.assertFalse(self.paths) + self.assertEqual(len(self.paths), 0) completion = my_completer.complete(self.tempdir, num_paths) - self.assertEqual(completion, None) + self.assertIsNone(completion) @unittest.skipIf('readline' not in sys.modules, reason='Not relevant if readline is not available.') @@ -98,7 +98,7 @@ class CompleterTest(test_util.TempDirTestCase): with completer.Completer(): pass - self.assertTrue(mock_readline.parse_and_bind.called) + self.assertIs(mock_readline.parse_and_bind.called, True) def enable_tab_completion(unused_command): diff --git a/certbot/tests/display/ops_test.py b/certbot/tests/display/ops_test.py index 1e50ba03b..aeb3ea525 100644 --- a/certbot/tests/display/ops_test.py +++ b/certbot/tests/display/ops_test.py @@ -61,9 +61,9 @@ class GetEmailTest(unittest.TestCase): with mock.patch("certbot.display.ops.util.safe_email") as mock_safe_email: mock_safe_email.return_value = True self._call() - self.assertTrue(invalid_txt not in mock_input.call_args[0][0]) + self.assertNotIn(invalid_txt, mock_input.call_args[0][0]) self._call(invalid=True) - self.assertTrue(invalid_txt in mock_input.call_args[0][0]) + self.assertIn(invalid_txt, mock_input.call_args[0][0]) @test_util.patch_get_utility("certbot.display.ops.z_util") def test_optional_flag(self, mock_get_utility): @@ -73,8 +73,7 @@ class GetEmailTest(unittest.TestCase): mock_safe_email.side_effect = [False, True] self._call(optional=False) for call in mock_input.call_args_list: - self.assertTrue( - "--register-unsafely-without-email" not in call[0][0]) + self.assertNotIn("--register-unsafely-without-email", call[0][0]) @test_util.patch_get_utility("certbot.display.ops.z_util") def test_optional_invalid_unsafe(self, mock_get_utility): @@ -84,7 +83,7 @@ class GetEmailTest(unittest.TestCase): with mock.patch("certbot.display.ops.util.safe_email") as mock_safe_email: mock_safe_email.side_effect = [False, True] self._call(invalid=True) - self.assertTrue(invalid_txt in mock_input.call_args[0][0]) + self.assertIn(invalid_txt, mock_input.call_args[0][0]) class ChooseAccountTest(test_util.TempDirTestCase): @@ -128,7 +127,7 @@ class ChooseAccountTest(test_util.TempDirTestCase): @test_util.patch_get_utility("certbot.display.ops.z_util") def test_cancel(self, mock_util): mock_util().menu.return_value = (display_util.CANCEL, 1) - self.assertTrue(self._call([self.acc1, self.acc2]) is None) + self.assertIsNone(self._call([self.acc1, self.acc2])) class GenHttpsNamesTest(unittest.TestCase): @@ -210,8 +209,7 @@ class ChooseNamesTest(unittest.TestCase): actual_doms = self._call(self.mock_install) self.assertEqual(mock_util().input.call_count, 1) self.assertEqual(actual_doms, [domain]) - self.assertTrue( - "configuration files" in mock_util().input.call_args[0][0]) + self.assertIn("configuration files", mock_util().input.call_args[0][0]) def test_sort_names_trivial(self): from certbot.display.ops import _sort_names @@ -353,7 +351,7 @@ class SuccessInstallationTest(unittest.TestCase): arg = mock_util().notification.call_args_list[0][0][0] for name in names: - self.assertTrue(name in arg) + self.assertIn(name, arg) class SuccessRenewalTest(unittest.TestCase): @@ -374,7 +372,7 @@ class SuccessRenewalTest(unittest.TestCase): arg = mock_util().notification.call_args_list[0][0][0] for name in names: - self.assertTrue(name in arg) + self.assertIn(name, arg) class SuccessRevocationTest(unittest.TestCase): """Test the success revocation message.""" @@ -478,8 +476,8 @@ class ChooseValuesTest(unittest.TestCase): mock_util().checklist.return_value = (display_util.OK, [items[2]]) result = self._call(items, None) self.assertEqual(result, [items[2]]) - self.assertTrue(mock_util().checklist.called) - self.assertEqual(mock_util().checklist.call_args[0][0], None) + self.assertIs(mock_util().checklist.called, True) + self.assertIsNone(mock_util().checklist.call_args[0][0]) @test_util.patch_get_utility("certbot.display.ops.z_util") def test_choose_names_success_question(self, mock_util): @@ -488,7 +486,7 @@ class ChooseValuesTest(unittest.TestCase): mock_util().checklist.return_value = (display_util.OK, [items[1]]) result = self._call(items, question) self.assertEqual(result, [items[1]]) - self.assertTrue(mock_util().checklist.called) + self.assertIs(mock_util().checklist.called, True) self.assertEqual(mock_util().checklist.call_args[0][0], question) @test_util.patch_get_utility("certbot.display.ops.z_util") @@ -498,7 +496,7 @@ class ChooseValuesTest(unittest.TestCase): mock_util().checklist.return_value = (display_util.CANCEL, []) result = self._call(items, question) self.assertEqual(result, []) - self.assertTrue(mock_util().checklist.called) + self.assertIs(mock_util().checklist.called, True) self.assertEqual(mock_util().checklist.call_args[0][0], question) diff --git a/certbot/tests/display/util_test.py b/certbot/tests/display/util_test.py index 5f1fac8c0..ca7ecf908 100644 --- a/certbot/tests/display/util_test.py +++ b/certbot/tests/display/util_test.py @@ -74,7 +74,7 @@ class FileOutputDisplayTest(unittest.TestCase): self.displayer.notification("message", False) string = self.mock_stdout.write.call_args[0][0] - self.assertTrue("message" in string) + self.assertIn("message", string) mock_logger.debug.assert_called_with("Notifying user: %s", "message") def test_notification_pause(self): @@ -82,25 +82,25 @@ class FileOutputDisplayTest(unittest.TestCase): with mock.patch(input_with_timeout, return_value="enter"): self.displayer.notification("message", force_interactive=True) - self.assertTrue("message" in self.mock_stdout.write.call_args[0][0]) + self.assertIn("message", self.mock_stdout.write.call_args[0][0]) def test_notification_noninteractive(self): self._force_noninteractive(self.displayer.notification, "message") string = self.mock_stdout.write.call_args[0][0] - self.assertTrue("message" in string) + self.assertIn("message", string) def test_notification_noninteractive2(self): # The main purpose of this test is to make sure we only call # logger.warning once which _force_noninteractive checks internally self._force_noninteractive(self.displayer.notification, "message") string = self.mock_stdout.write.call_args[0][0] - self.assertTrue("message" in string) + self.assertIn("message", string) self.assertTrue(self.displayer.skipped_interaction) self._force_noninteractive(self.displayer.notification, "message2") string = self.mock_stdout.write.call_args[0][0] - self.assertTrue("message2" in string) + self.assertIn("message2", string) def test_notification_decoration(self): from certbot.compat import os @@ -110,7 +110,8 @@ class FileOutputDisplayTest(unittest.TestCase): self.displayer.notification("message2", pause=False) string = self.mock_stdout.write.call_args[0][0] - self.assertTrue("- - - " in string and ("message2" + os.linesep) in string) + self.assertIn("- - - ", string) + self.assertIn("message2" + os.linesep, string) @mock.patch("certbot.display.util." "FileDisplay._get_valid_int_ans") @@ -265,7 +266,7 @@ class FileOutputDisplayTest(unittest.TestCase): result = func(*args, **kwargs) if skipped_interaction: - self.assertFalse(mock_logger.warning.called) + self.assertIs(mock_logger.warning.called, False) else: self.assertEqual(mock_logger.warning.call_count, 1) @@ -331,7 +332,7 @@ class FileOutputDisplayTest(unittest.TestCase): # force_interactive to prevent workflow regressions. for name in interfaces.IDisplay.names(): arg_spec = inspect.getfullargspec(getattr(self.displayer, name)) - self.assertTrue("force_interactive" in arg_spec.args) + self.assertIn("force_interactive", arg_spec.args) class NoninteractiveDisplayTest(unittest.TestCase): @@ -345,7 +346,7 @@ class NoninteractiveDisplayTest(unittest.TestCase): self.displayer.notification("message", 10) string = self.mock_stdout.write.call_args[0][0] - self.assertTrue("message" in string) + self.assertIn("message", string) mock_logger.debug.assert_called_with("Notifying user: %s", "message") def test_notification_decoration(self): @@ -401,7 +402,7 @@ class NoninteractiveDisplayTest(unittest.TestCase): method = getattr(self.displayer, name) # asserts method accepts arbitrary keyword arguments result = inspect.getfullargspec(method).varkw - self.assertFalse(result is None) + self.assertIsNotNone(result) class SeparateListInputTest(unittest.TestCase): diff --git a/certbot/tests/eff_test.py b/certbot/tests/eff_test.py index 5da1e6fb6..0527d87d9 100644 --- a/certbot/tests/eff_test.py +++ b/certbot/tests/eff_test.py @@ -50,7 +50,7 @@ class PrepareSubscriptionTest(SubscriptionTest): self._call() actual = mock_notify.call_args[0][0] expected_part = "because you didn't provide an e-mail address" - self.assertTrue(expected_part in actual) + self.assertIn(expected_part, actual) self.assertIsNone(self.account.meta.register_to_eff) @test_util.patch_get_utility() @@ -92,7 +92,7 @@ class PrepareSubscriptionTest(SubscriptionTest): call_args, call_kwargs = mock_get_utility().yesno.call_args actual = call_args[0] expected_part = 'Electronic Frontier Foundation' - self.assertTrue(expected_part in actual) + self.assertIn(expected_part, actual) self.assertFalse(call_kwargs.get('default', True)) @@ -105,7 +105,7 @@ class HandleSubscriptionTest(SubscriptionTest): @mock.patch('certbot._internal.eff.subscribe') def test_no_subscribe(self, mock_subscribe): self._call() - self.assertFalse(mock_subscribe.called) + self.assertIs(mock_subscribe.called, False) @mock.patch('certbot._internal.eff.subscribe') def test_subscribe(self, mock_subscribe): @@ -140,7 +140,7 @@ class SubscribeTest(unittest.TestCase): self.assertEqual(call_args[0], constants.EFF_SUBSCRIBE_URI) data = call_kwargs.get('data') - self.assertFalse(data is None) + self.assertIsNotNone(data) self.assertEqual(data.get('email'), self.email) def test_bad_status(self): @@ -148,7 +148,7 @@ class SubscribeTest(unittest.TestCase): self._call() actual = self._get_reported_message() expected_part = 'because your e-mail address appears to be invalid.' - self.assertTrue(expected_part in actual) + self.assertIn(expected_part, actual) def test_not_ok(self): self.response.ok = False @@ -156,21 +156,21 @@ class SubscribeTest(unittest.TestCase): self._call() actual = self._get_reported_message() unexpected_part = 'because' - self.assertFalse(unexpected_part in actual) + self.assertNotIn(unexpected_part, actual) def test_response_not_json(self): self.response.json.side_effect = ValueError() self._call() actual = self._get_reported_message() expected_part = 'problem' - self.assertTrue(expected_part in actual) + self.assertIn(expected_part, actual) def test_response_json_missing_status_element(self): self.json.clear() self._call() actual = self._get_reported_message() expected_part = 'problem' - self.assertTrue(expected_part in actual) + self.assertIn(expected_part, actual) def _get_reported_message(self): self.assertTrue(self.mock_notify.called) @@ -179,7 +179,7 @@ class SubscribeTest(unittest.TestCase): @test_util.patch_get_utility() def test_subscribe(self, mock_get_utility): self._call() - self.assertFalse(mock_get_utility.called) + self.assertIs(mock_get_utility.called, False) if __name__ == '__main__': diff --git a/certbot/tests/error_handler_test.py b/certbot/tests/error_handler_test.py index e04fe0742..ee4c2215d 100644 --- a/certbot/tests/error_handler_test.py +++ b/certbot/tests/error_handler_test.py @@ -120,7 +120,7 @@ class ErrorHandlerTest(unittest.TestCase): sys.exit(0) except SystemExit: pass - self.assertFalse(self.init_func.called) + self.assertIs(self.init_func.called, False) def test_regular_exit(self): func = mock.MagicMock() diff --git a/certbot/tests/helpful_test.py b/certbot/tests/helpful_test.py index 1a5c2bea6..0abe277bf 100644 --- a/certbot/tests/helpful_test.py +++ b/certbot/tests/helpful_test.py @@ -18,10 +18,10 @@ class TestScanningFlags(unittest.TestCase): arg_parser = HelpfulArgumentParser(['run'], {}) detected_flag = arg_parser.prescan_for_flag('--help', ['all', 'certonly']) - self.assertFalse(detected_flag) + self.assertIs(detected_flag, False) detected_flag = arg_parser.prescan_for_flag('-h', ['all, certonly']) - self.assertFalse(detected_flag) + self.assertIs(detected_flag, False) def test_prescan_unvalid_topic(self): arg_parser = HelpfulArgumentParser(['--help', 'all'], {}) @@ -30,7 +30,7 @@ class TestScanningFlags(unittest.TestCase): self.assertIs(detected_flag, True) detected_flag = arg_parser.prescan_for_flag('-h', arg_parser.help_topics) - self.assertFalse(detected_flag) + self.assertIs(detected_flag, False) def test_prescan_valid_topic(self): arg_parser = HelpfulArgumentParser(['-h', 'all'], {}) @@ -39,7 +39,7 @@ class TestScanningFlags(unittest.TestCase): self.assertEqual(detected_flag, 'all') detected_flag = arg_parser.prescan_for_flag('--help', arg_parser.help_topics) - self.assertFalse(detected_flag) + self.assertIs(detected_flag, False) class TestDetermineVerbs(unittest.TestCase): '''Tests for determine_verb methods of HelpfulArgumentParser''' @@ -90,7 +90,7 @@ class TestAdd(unittest.TestCase): metavar="EAB_KID", help="Key Identifier for External Account Binding") parsed_args = arg_parser.parser.parse_args(["--eab-kid", None]) - self.assertIs(parsed_args.eab_kid, None) + self.assertIsNone(parsed_args.eab_kid) self.assertTrue(hasattr(parsed_args, 'eab_kid')) @@ -115,7 +115,7 @@ class TestAddGroup(unittest.TestCase): self.assertTrue(arg_parser.groups["run"]) arg_parser.add_group("certonly", description="description of certonly") with self.assertRaises(KeyError): - self.assertFalse(arg_parser.groups["certonly"]) + self.assertIs(arg_parser.groups["certonly"], False) class TestParseArgsErrors(unittest.TestCase): diff --git a/certbot/tests/hook_test.py b/certbot/tests/hook_test.py index 76d460ae9..bcef2e398 100644 --- a/certbot/tests/hook_test.py +++ b/certbot/tests/hook_test.py @@ -59,7 +59,7 @@ class ValidateHookTest(test_util.TempDirTestCase): @mock.patch("certbot._internal.hooks._prog") def test_unset(self, mock_prog): self._call(None, "foo") - self.assertFalse(mock_prog.called) + self.assertIs(mock_prog.called, False) class HookTest(test_util.ConfigTestCase): @@ -132,8 +132,8 @@ class PreHookTest(HookTest): with mock.patch("certbot._internal.hooks.logger") as mock_logger: mock_execute = self._call_with_mock_execute(self.config) - self.assertFalse(mock_execute.called) - self.assertFalse(mock_logger.info.called) + self.assertIs(mock_execute.called, False) + self.assertIs(mock_logger.info.called, False) def test_renew_disabled_dir_hooks(self): self.config.directory_hooks = False @@ -158,7 +158,7 @@ class PreHookTest(HookTest): def _test_no_executions_common(self): with mock.patch("certbot._internal.hooks.logger") as mock_logger: mock_execute = self._call_with_mock_execute(self.config) - self.assertFalse(mock_execute.called) + self.assertIs(mock_execute.called, False) self.assertTrue(mock_logger.info.called) @@ -344,7 +344,7 @@ class DeployHookTest(RenewalHookTest): self.config.dry_run = True mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertFalse(mock_execute.called) + self.assertIs(mock_execute.called, False) self.assertTrue(mock_logger.warning.called) @mock.patch("certbot._internal.hooks.logger") @@ -352,8 +352,8 @@ class DeployHookTest(RenewalHookTest): self.config.deploy_hook = None mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertFalse(mock_execute.called) - self.assertFalse(mock_logger.info.called) + self.assertIs(mock_execute.called, False) + self.assertIs(mock_logger.info.called, False) def test_success(self): domains = ["example.org", "example.net"] @@ -392,7 +392,7 @@ class RenewHookTest(RenewalHookTest): self.config.dry_run = True mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertFalse(mock_execute.called) + self.assertIs(mock_execute.called, False) self.assertEqual(mock_logger.warning.call_count, 2) def test_no_hooks(self): @@ -402,8 +402,8 @@ class RenewHookTest(RenewalHookTest): with mock.patch("certbot._internal.hooks.logger") as mock_logger: mock_execute = self._call_with_mock_execute( self.config, ["example.org"], "/foo/bar") - self.assertFalse(mock_execute.called) - self.assertFalse(mock_logger.info.called) + self.assertIs(mock_execute.called, False) + self.assertIs(mock_logger.info.called, False) def test_overlap(self): self.config.renew_hook = self.dir_hook diff --git a/certbot/tests/lock_test.py b/certbot/tests/lock_test.py index ac6b539a4..b45eb8f7a 100644 --- a/certbot/tests/lock_test.py +++ b/certbot/tests/lock_test.py @@ -69,7 +69,7 @@ class LockFileTest(test_util.TempDirTestCase): try: locked_repr = repr(lock_file) self._test_repr_common(lock_file, locked_repr) - self.assertTrue('acquired' in locked_repr) + self.assertIn('acquired', locked_repr) finally: lock_file.release() @@ -78,11 +78,11 @@ class LockFileTest(test_util.TempDirTestCase): lock_file.release() released_repr = repr(lock_file) self._test_repr_common(lock_file, released_repr) - self.assertTrue('released' in released_repr) + self.assertIn('released', released_repr) def _test_repr_common(self, lock_file, lock_repr): - self.assertTrue(lock_file.__class__.__name__ in lock_repr) - self.assertTrue(self.lock_path in lock_repr) + self.assertIn(lock_file.__class__.__name__, lock_repr) + self.assertIn(self.lock_path, lock_repr) @test_util.skip_on_windows( 'Race conditions on lock are specific to the non-blocking file access approach on Linux.') @@ -102,7 +102,7 @@ class LockFileTest(test_util.TempDirTestCase): with mock.patch('certbot._internal.lock.filesystem.os.stat') as mock_stat: mock_stat.side_effect = delete_and_stat self._call(self.lock_path) - self.assertFalse(should_delete) + self.assertEqual(len(should_delete), 0) def test_removed(self): lock_file = self._call(self.lock_path) @@ -120,7 +120,7 @@ class LockFileTest(test_util.TempDirTestCase): try: self._call(self.lock_path) except IOError as err: - self.assertTrue(msg in str(err)) + self.assertIn(msg, str(err)) else: # pragma: no cover self.fail('IOError not raised') @@ -136,7 +136,7 @@ class LockFileTest(test_util.TempDirTestCase): try: self._call(self.lock_path) except OSError as err: - self.assertTrue(msg in str(err)) + self.assertIn(msg, str(err)) else: # pragma: no cover self.fail('OSError not raised') diff --git a/certbot/tests/log_test.py b/certbot/tests/log_test.py index 37660f51e..12daf0000 100644 --- a/certbot/tests/log_test.py +++ b/certbot/tests/log_test.py @@ -51,9 +51,8 @@ class PreArgParseSetupTest(unittest.TestCase): memory_handler = handler target = memory_handler.target # type: ignore else: - self.assertTrue(isinstance(handler, logging.StreamHandler)) - self.assertTrue( - isinstance(target, logging.StreamHandler)) + self.assertIsInstance(handler, logging.StreamHandler) + self.assertIsInstance(target, logging.StreamHandler) mock_register.assert_called_once_with(logging.shutdown) mock_sys.excepthook(1, 2, 3) @@ -146,7 +145,7 @@ class SetupLogFileHandlerTest(test_util.ConfigTestCase): try: self._call(self.config, 'test.log', '%(message)s') except errors.Error as err: - self.assertTrue('--logs-dir' in str(err)) + self.assertIn('--logs-dir', str(err)) else: # pragma: no cover self.fail('Error not raised.') @@ -337,7 +336,7 @@ class PostArgParseExceptHookTest(unittest.TestCase): mock_logger, output = self._test_common(get_acme_error, debug=False) self._assert_exception_logged(mock_logger.debug, messages.Error) self._assert_quiet_output(mock_logger, output) - self.assertFalse(messages.ERROR_PREFIX in output) + self.assertNotIn(messages.ERROR_PREFIX, output) def test_other_error(self): exc_type = ValueError @@ -379,20 +378,20 @@ class PostArgParseExceptHookTest(unittest.TestCase): def _assert_exception_logged(self, log_func, exc_type): self.assertTrue(log_func.called) call_kwargs = log_func.call_args[1] - self.assertTrue('exc_info' in call_kwargs) + self.assertIn('exc_info', call_kwargs) actual_exc_info = call_kwargs['exc_info'] expected_exc_info = (exc_type, mock.ANY, mock.ANY) self.assertEqual(actual_exc_info, expected_exc_info) def _assert_logfile_output(self, output): - self.assertTrue('Please see the logfile' in output) - self.assertTrue(self.log_path in output) + self.assertIn('Please see the logfile', output) + self.assertIn(self.log_path, output) def _assert_quiet_output(self, mock_logger, output): - self.assertFalse(mock_logger.exception.called) + self.assertIs(mock_logger.exception.called, False) self.assertTrue(mock_logger.debug.called) - self.assertTrue(self.error_msg in output) + self.assertIn(self.error_msg, output) class ExitWithLogPathTest(test_util.TempDirTestCase): @@ -407,13 +406,13 @@ class ExitWithLogPathTest(test_util.TempDirTestCase): open(log_file, 'w').close() err_str = self._test_common(log_file) - self.assertTrue('logfiles' not in err_str) - self.assertTrue(log_file in err_str) + self.assertNotIn('logfiles', err_str) + self.assertIn(log_file, err_str) def test_log_dir(self): err_str = self._test_common(self.tempdir) - self.assertTrue('logfiles' in err_str) - self.assertTrue(self.tempdir in err_str) + self.assertIn('logfiles', err_str) + self.assertIn(self.tempdir, err_str) # pylint: disable=inconsistent-return-statements def _test_common(self, *args, **kwargs): diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 7908cf804..5689c0281 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -84,17 +84,17 @@ class TestHandleCerts(unittest.TestCase): mock_set.return_value = False with self.assertRaises(errors.Error) as raised: main._handle_unexpected_key_type_migration(config, cert) - self.assertTrue("Please provide both --cert-name and --key-type" in str(raised.exception)) + self.assertIn("Please provide both --cert-name and --key-type", str(raised.exception)) mock_set.side_effect = lambda var: var != "certname" with self.assertRaises(errors.Error) as raised: main._handle_unexpected_key_type_migration(config, cert) - self.assertTrue("Please provide both --cert-name and --key-type" in str(raised.exception)) + self.assertIn("Please provide both --cert-name and --key-type", str(raised.exception)) mock_set.side_effect = lambda var: var != "key_type" with self.assertRaises(errors.Error) as raised: main._handle_unexpected_key_type_migration(config, cert) - self.assertTrue("Please provide both --cert-name and --key-type" in str(raised.exception)) + self.assertIn("Please provide both --cert-name and --key-type", str(raised.exception)) class RunTest(test_util.ConfigTestCase): @@ -196,7 +196,7 @@ class CertonlyTest(unittest.TestCase): self._call('certonly --webroot -d example.com'.split()) def _assert_no_pause(self, message, pause=True): # pylint: disable=unused-argument - self.assertFalse(pause) + self.assertIs(pause, False) @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @mock.patch('certbot._internal.cert_manager.domains_for_certname') @@ -260,8 +260,7 @@ class FindDomainsOrCertnameTest(unittest.TestCase): mock_config = mock.Mock(domains=None, certname=None) mock_choose_names.return_value = "domainname" # pylint: disable=protected-access - self.assertEqual(main._find_domains_or_certname(mock_config, None), - ("domainname", None)) + self.assertEqual(main._find_domains_or_certname(mock_config, None), ("domainname", None)) @mock.patch('certbot.display.ops.choose_names') def test_no_results(self, mock_choose_names): @@ -275,8 +274,10 @@ class FindDomainsOrCertnameTest(unittest.TestCase): mock_config = mock.Mock(domains=None, certname="one.com") mock_domains.return_value = ["one.com", "two.com"] # pylint: disable=protected-access - self.assertEqual(main._find_domains_or_certname(mock_config, None), - (["one.com", "two.com"], "one.com")) + self.assertEqual( + main._find_domains_or_certname(mock_config, None), + (["one.com", "two.com"], "one.com") + ) class RevokeTest(test_util.TempDirTestCase): @@ -402,7 +403,7 @@ class RevokeTest(test_util.TempDirTestCase): mock_get_utility().yesno.return_value = False mock_delete_if_appropriate.return_value = False self._call() - self.assertFalse(mock_delete.called) + self.assertIs(mock_delete.called, False) class DeleteIfAppropriateTest(test_util.ConfigTestCase): """Tests for certbot._internal.main._delete_if_appropriate """ @@ -536,13 +537,13 @@ class DetermineAccountTest(test_util.ConfigTestCase): self.config.account = self.accs[1].id self.assertEqual((self.accs[1], None), self._call()) self.assertEqual(self.accs[1].id, self.config.account) - self.assertTrue(self.config.email is None) + self.assertIsNone(self.config.email) def test_single_account(self): self.account_storage.save(self.accs[0], self.mock_client) self.assertEqual((self.accs[0], None), self._call()) self.assertEqual(self.accs[0].id, self.config.account) - self.assertTrue(self.config.email is None) + self.assertIsNone(self.config.email) @mock.patch('certbot._internal.client.display_ops.choose_account') def test_multiple_accounts(self, mock_choose_accounts): @@ -553,7 +554,7 @@ class DetermineAccountTest(test_util.ConfigTestCase): self.assertEqual( set(mock_choose_accounts.call_args[0][0]), set(self.accs)) self.assertEqual(self.accs[1].id, self.config.account) - self.assertTrue(self.config.email is None) + self.assertIsNone(self.config.email) @mock.patch('certbot._internal.client.display_ops.get_email') @mock.patch('certbot._internal.main.display_util.notify') @@ -651,7 +652,7 @@ class MainTest(test_util.ConfigTestCase): pass finally: output = toy_out.getvalue() or toy_err.getvalue() - self.assertTrue("certbot" in output, "Output is {0}".format(output)) + self.assertIn("certbot", output, "Output is {0}".format(output)) def _cli_missing_flag(self, args, message): "Ensure that a particular error raises a missing cli flag error containing message" @@ -661,8 +662,8 @@ class MainTest(test_util.ConfigTestCase): main.main(self.standard_args + args[:]) # NOTE: parser can alter its args! except errors.MissingCommandlineFlag as exc_: exc = exc_ - self.assertTrue(message in str(exc)) - self.assertTrue(exc is not None) + self.assertIn(message, str(exc)) + self.assertIsNotNone(exc) @mock.patch('certbot._internal.log.post_arg_parse_setup') def test_noninteractive(self, _): @@ -690,11 +691,11 @@ class MainTest(test_util.ConfigTestCase): self._call_no_clientmock(args) os_ver = util.get_os_info_ua() ua = acme_net.call_args[1]["user_agent"] - self.assertTrue(os_ver in ua) + self.assertIn(os_ver, ua) import platform plat = platform.platform() if "linux" in plat.lower(): - self.assertTrue(util.get_os_info_ua() in ua) + self.assertIn(util.get_os_info_ua(), ua) with mock.patch('certbot._internal.main.client.acme_client.ClientNetwork') as acme_net: ua = "bandersnatch" @@ -803,8 +804,8 @@ class MainTest(test_util.ConfigTestCase): # Sending nginx a non-existent conf dir will simulate misconfiguration # (we can only do that if certbot-nginx is actually present) ret, _, _, _ = self._call(args) - self.assertTrue("The nginx plugin is not working" in ret) - self.assertTrue("MisconfigurationError" in ret) + self.assertIn("The nginx plugin is not working", ret) + self.assertIn("MisconfigurationError", ret) self._cli_missing_flag(["--standalone"], "With the standalone plugin, you probably") @@ -813,7 +814,7 @@ class MainTest(test_util.ConfigTestCase): mock_gsc.return_value = mock.MagicMock() self._call(["certonly", "--manual", "-d", "foo.bar"]) unused_config, auth, unused_installer = mock_init.call_args[0] - self.assertTrue(isinstance(auth, manual.Authenticator)) + self.assertIsInstance(auth, manual.Authenticator) with mock.patch('certbot._internal.main.certonly') as mock_certonly: self._call(["auth", "--standalone"]) @@ -951,7 +952,7 @@ class MainTest(test_util.ConfigTestCase): self._call(['-a', 'bad_auth', 'certonly']) assert False, "Exception should have been raised" except errors.PluginSelectionError as e: - self.assertTrue('The requested bad_auth plugin does not appear' in str(e)) + self.assertIn('The requested bad_auth plugin does not appear', str(e)) def test_check_config_sanity_domain(self): # FQDN @@ -1010,8 +1011,7 @@ class MainTest(test_util.ConfigTestCase): self._certonly_new_request_common(mock_client, ['--dry-run']) self.assertEqual( mock_client.obtain_and_enroll_certificate.call_count, 1) - self.assertTrue( - 'dry run' in mock_get_utility().add_message.call_args[0][0]) + self.assertIn('dry run', mock_get_utility().add_message.call_args[0][0]) # Asserts we don't suggest donating after a successful dry run self.assertEqual(mock_get_utility().add_message.call_count, 1) @@ -1032,12 +1032,11 @@ class MainTest(test_util.ConfigTestCase): self.assertEqual( mock_client.obtain_and_enroll_certificate.call_count, 1) cert_msg = mock_get_utility().add_message.call_args_list[0][0][0] - self.assertTrue(cert_path in cert_msg) - self.assertTrue(date in cert_msg) - self.assertTrue(key_path in cert_msg) - self.assertTrue( - 'donate' in mock_get_utility().add_message.call_args[0][0]) - self.assertTrue(mock_subscription.called) + self.assertIn(cert_path, cert_msg) + self.assertIn(date, cert_msg) + self.assertIn(key_path, cert_msg) + self.assertIn('donate', mock_get_utility().add_message.call_args[0][0]) + self.assertIs(mock_subscription.called, True) @mock.patch('certbot._internal.eff.handle_subscription') def test_certonly_new_request_failure(self, mock_subscription): @@ -1045,7 +1044,7 @@ class MainTest(test_util.ConfigTestCase): mock_client.obtain_and_enroll_certificate.return_value = False self.assertRaises(errors.Error, self._certonly_new_request_common, mock_client) - self.assertFalse(mock_subscription.called) + self.assertIs(mock_subscription.called, False) def _test_renewal_common(self, due_for_renewal, extra_args, log_out=None, args=None, should_renew=True, error_expected=False, @@ -1120,7 +1119,7 @@ class MainTest(test_util.ConfigTestCase): finally: if log_out: with open(os.path.join(self.config.logs_dir, "letsencrypt.log")) as lf: - self.assertTrue(log_out in lf.read()) + self.assertIn(log_out, lf.read()) return mock_lineage, mock_get_utility, stdout @@ -1131,8 +1130,8 @@ class MainTest(test_util.ConfigTestCase): lineage.update_all_links_to.assert_called_once_with( lineage.latest_common_version()) cert_msg = get_utility().add_message.call_args_list[0][0][0] - self.assertTrue('fullchain.pem' in cert_msg) - self.assertTrue('donate' in get_utility().add_message.call_args[0][0]) + self.assertIn('fullchain.pem', cert_msg) + self.assertIn('donate', get_utility().add_message.call_args[0][0]) @mock.patch('certbot._internal.log.logging.handlers.RotatingFileHandler.doRollover') @mock.patch('certbot.crypto_util.notAfter') @@ -1141,7 +1140,7 @@ class MainTest(test_util.ConfigTestCase): _, get_utility, _ = self._test_renewal_common(False, ['--dry-run', '--keep'], log_out="simulating renewal") self.assertEqual(get_utility().add_message.call_count, 1) - self.assertTrue('dry run' in get_utility().add_message.call_args[0][0]) + self.assertIn('dry run', get_utility().add_message.call_args[0][0]) self._test_renewal_common(False, ['--renew-by-default', '-tvv', '--debug'], log_out="Auto-renewal forced") @@ -1200,8 +1199,8 @@ class MainTest(test_util.ConfigTestCase): expiry = datetime.datetime.now() + datetime.timedelta(days=90) _, _, stdout = self._test_renewal_common(False, extra_args=None, should_renew=False, args=['renew'], expiry_date=expiry) - self.assertTrue('No renewals were attempted.' in stdout.getvalue()) - self.assertTrue('The following certificates are not due for renewal yet:' in stdout.getvalue()) + self.assertIn('No renewals were attempted.', stdout.getvalue()) + self.assertIn('The following certificates are not due for renewal yet:', stdout.getvalue()) @mock.patch('certbot._internal.log.post_arg_parse_setup') def test_quiet_renew(self, _): @@ -1209,7 +1208,7 @@ class MainTest(test_util.ConfigTestCase): args = ["renew", "--dry-run"] _, _, stdout = self._test_renewal_common(True, [], args=args, should_renew=True) out = stdout.getvalue() - self.assertTrue("renew" in out) + self.assertIn("renew", out) args = ["renew", "--dry-run", "-q"] _, _, stdout = self._test_renewal_common(True, [], args=args, @@ -1275,7 +1274,7 @@ class MainTest(test_util.ConfigTestCase): if assert_oc_called: self.assertTrue(mock_renew_cert.called) else: - self.assertFalse(mock_renew_cert.called) + self.assertIs(mock_renew_cert.called, False) def test_renew_no_renewalparams(self): self._test_renew_common(assert_oc_called=False, error_expected=True) @@ -1354,7 +1353,7 @@ class MainTest(test_util.ConfigTestCase): args=['renew', '--post-hook', '{0} -c "print(\'hello world\');"' .format(sys.executable)]) - self.assertTrue('No hooks were run.' in stdout.getvalue()) + self.assertIn('No hooks were run.', stdout.getvalue()) @test_util.patch_get_utility() @mock.patch('certbot._internal.main._find_lineage_for_domains_and_certname') @@ -1365,8 +1364,8 @@ class MainTest(test_util.ConfigTestCase): mock_renewal.return_value = ('reinstall', mock.MagicMock()) mock_init.return_value = mock_client = mock.MagicMock() self._call(['-d', 'foo.bar', '-a', 'standalone', 'certonly']) - self.assertFalse(mock_client.obtain_certificate.called) - self.assertFalse(mock_client.obtain_and_enroll_certificate.called) + self.assertIs(mock_client.obtain_certificate.called, False) + self.assertIs(mock_client.obtain_and_enroll_certificate.called, False) self.assertEqual(mock_get_utility().add_message.call_count, 0) mock_report_new_cert.assert_not_called() #self.assertTrue('donate' not in mock_get_utility().add_message.call_args[0][0]) @@ -1398,7 +1397,7 @@ class MainTest(test_util.ConfigTestCase): self._call(args) if '--dry-run' in args: - self.assertFalse(mock_client.save_certificate.called) + self.assertIs(mock_client.save_certificate.called, False) else: mock_client.save_certificate.assert_called_once_with( certr, chain, cert_path, chain_path, full_path) @@ -1409,17 +1408,15 @@ class MainTest(test_util.ConfigTestCase): def test_certonly_csr(self, mock_subscription): mock_get_utility = self._test_certonly_csr_common() cert_msg = mock_get_utility().add_message.call_args_list[0][0][0] - self.assertTrue('fullchain.pem' in cert_msg) - self.assertFalse('Your key file has been saved at' in cert_msg) - self.assertTrue( - 'donate' in mock_get_utility().add_message.call_args[0][0]) - self.assertTrue(mock_subscription.called) + self.assertIn('fullchain.pem', cert_msg) + self.assertNotIn('Your key file has been saved at', cert_msg) + self.assertIn('donate', mock_get_utility().add_message.call_args[0][0]) + self.assertIs(mock_subscription.called, True) def test_certonly_csr_dry_run(self): mock_get_utility = self._test_certonly_csr_common(['--dry-run']) self.assertEqual(mock_get_utility().add_message.call_count, 1) - self.assertTrue( - 'dry run' in mock_get_utility().add_message.call_args[0][0]) + self.assertIn('dry run', mock_get_utility().add_message.call_args[0][0]) @mock.patch('certbot._internal.main._delete_if_appropriate') @mock.patch('certbot._internal.main.client.acme_client') @@ -1474,7 +1471,7 @@ class MainTest(test_util.ConfigTestCase): mocked_account.AccountFileStorage.return_value = mocked_storage mocked_storage.find_all.return_value = ["an account"] x = self._call_no_clientmock(["register", "--email", "user@example.org"]) - self.assertTrue("There is an existing account" in x[0]) + self.assertIn("There is an existing account", x[0]) @mock.patch('certbot._internal.plugins.selection.choose_configurator_plugins') @mock.patch('certbot._internal.updater._run_updaters') @@ -1487,7 +1484,7 @@ class MainTest(test_util.ConfigTestCase): updater.run_generic_updaters(self.config, None, None) # Make sure we're returning None, and hence not trying to run the # without installer - self.assertFalse(mock_run.called) + self.assertIs(mock_run.called, False) class UnregisterTest(unittest.TestCase): @@ -1531,7 +1528,7 @@ class UnregisterTest(unittest.TestCase): res = main.unregister(config, unused_plugins) - self.assertTrue(res is None) + self.assertIsNone(res) mock_notify.assert_called_once_with("Account deactivated.") def test_unregister_no_account(self): @@ -1548,7 +1545,7 @@ class UnregisterTest(unittest.TestCase): res = main.unregister(config, unused_plugins) m = "Could not find existing account to deactivate." self.assertEqual(res, m) - self.assertFalse(cb_client.acme.deactivate_registration.called) + self.assertIs(cb_client.acme.deactivate_registration.called, False) class MakeOrVerifyNeededDirs(test_util.ConfigTestCase): @@ -1612,7 +1609,7 @@ class EnhanceTest(test_util.ConfigTestCase): self._call(['enhance', '--redirect']) self.assertTrue(mock_pick.called) # Check that the message includes "enhancements" - self.assertTrue("enhancements" in mock_pick.call_args[0][3]) + self.assertIn("enhancements", mock_pick.call_args[0][3]) @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -1626,7 +1623,7 @@ class EnhanceTest(test_util.ConfigTestCase): with mock.patch('certbot._internal.main.plug_sel.logger.warning') as mock_log: mock_client = self._call(['enhance', '-a', 'webroot', '--redirect']) self.assertTrue(mock_log.called) - self.assertTrue("make sense" in mock_log.call_args[0][0]) + self.assertIn("make sense", mock_log.call_args[0][0]) self.assertTrue(mock_client.enhance_config.called) @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @@ -1644,8 +1641,8 @@ class EnhanceTest(test_util.ConfigTestCase): all(getattr(mock_client.config, e) for e in req_enh)) self.assertFalse( any(getattr(mock_client.config, e) for e in not_req_enh)) - self.assertTrue( - "example.com" in mock_client.enhance_config.call_args[0][0]) + self.assertIn( + "example.com", mock_client.enhance_config.call_args[0][0]) @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @mock.patch('certbot._internal.main.display_ops.choose_values') @@ -1658,7 +1655,7 @@ class EnhanceTest(test_util.ConfigTestCase): mock_client = self._call(['enhance', '--redirect', '--hsts', '--non-interactive']) self.assertTrue(mock_client.enhance_config.called) - self.assertFalse(mock_choose.called) + self.assertIs(mock_choose.called, False) @mock.patch('certbot._internal.main.display_ops.choose_values') @mock.patch('certbot._internal.main.plug_sel.record_chosen_plugins') @@ -1681,7 +1678,7 @@ class EnhanceTest(test_util.ConfigTestCase): mock_pick.return_value = (None, None) mock_pick.side_effect = errors.PluginSelectionError() mock_client = self._call(['enhance', '--hsts']) - self.assertFalse(mock_client.enhance_config.called) + self.assertIs(mock_client.enhance_config.called, False) @mock.patch('certbot._internal.cert_manager.lineage_for_certname') @mock.patch('certbot._internal.main.display_ops.choose_values') diff --git a/certbot/tests/ocsp_test.py b/certbot/tests/ocsp_test.py index fe89fff9f..72a39e2d1 100644 --- a/certbot/tests/ocsp_test.py +++ b/certbot/tests/ocsp_test.py @@ -68,14 +68,14 @@ class OCSPTestOpenSSL(unittest.TestCase): mock_communicate.communicate.return_value = (None, out.partition("\n")[2]) checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) self.assertEqual(checker.host_args("x"), ["Host", "x"]) - self.assertEqual(checker.broken, False) + self.assertIs(checker.broken, False) mock_exists.return_value = False mock_popen.call_count = 0 checker = ocsp.RevocationChecker(enforce_openssl_binary_usage=True) self.assertEqual(mock_popen.call_count, 0) self.assertEqual(mock_log.call_count, 1) - self.assertEqual(checker.broken, True) + self.assertIs(checker.broken, True) @mock.patch('certbot.ocsp._determine_ocsp_server') @mock.patch('certbot.ocsp.crypto_util.notAfter') @@ -89,24 +89,24 @@ class OCSPTestOpenSSL(unittest.TestCase): self.checker.broken = True mock_determine.return_value = ("", "") - self.assertEqual(self.checker.ocsp_revoked(cert_obj), False) + self.assertIs(self.checker.ocsp_revoked(cert_obj), False) self.checker.broken = False mock_run.return_value = tuple(openssl_happy[1:]) - self.assertEqual(self.checker.ocsp_revoked(cert_obj), False) + self.assertIs(self.checker.ocsp_revoked(cert_obj), False) self.assertEqual(mock_run.call_count, 0) mock_determine.return_value = ("http://x.co", "x.co") - self.assertEqual(self.checker.ocsp_revoked(cert_obj), False) + self.assertIs(self.checker.ocsp_revoked(cert_obj), False) mock_run.side_effect = errors.SubprocessError("Unable to load certificate launcher") - self.assertEqual(self.checker.ocsp_revoked(cert_obj), False) + self.assertIs(self.checker.ocsp_revoked(cert_obj), False) self.assertEqual(mock_run.call_count, 2) # cert expired mock_na.return_value = now mock_determine.return_value = ("", "") count_before = mock_determine.call_count - self.assertEqual(self.checker.ocsp_revoked(cert_obj), False) + self.assertIs(self.checker.ocsp_revoked(cert_obj), False) self.assertEqual(mock_determine.call_count, count_before) def test_determine_ocsp_server(self): @@ -122,22 +122,22 @@ class OCSPTestOpenSSL(unittest.TestCase): # pylint: disable=protected-access mock_run.return_value = openssl_confused from certbot import ocsp - self.assertEqual(ocsp._translate_ocsp_query(*openssl_happy), False) - self.assertEqual(ocsp._translate_ocsp_query(*openssl_confused), False) + self.assertIs(ocsp._translate_ocsp_query(*openssl_happy), False) + self.assertIs(ocsp._translate_ocsp_query(*openssl_confused), False) self.assertEqual(mock_log.debug.call_count, 1) self.assertEqual(mock_log.warning.call_count, 0) mock_log.debug.call_count = 0 - self.assertEqual(ocsp._translate_ocsp_query(*openssl_unknown), False) + self.assertIs(ocsp._translate_ocsp_query(*openssl_unknown), False) self.assertEqual(mock_log.debug.call_count, 1) self.assertEqual(mock_log.warning.call_count, 0) - self.assertEqual(ocsp._translate_ocsp_query(*openssl_expired_ocsp), False) + self.assertIs(ocsp._translate_ocsp_query(*openssl_expired_ocsp), False) self.assertEqual(mock_log.debug.call_count, 2) - self.assertEqual(ocsp._translate_ocsp_query(*openssl_broken), False) + self.assertIs(ocsp._translate_ocsp_query(*openssl_broken), False) self.assertEqual(mock_log.warning.call_count, 1) mock_log.info.call_count = 0 - self.assertEqual(ocsp._translate_ocsp_query(*openssl_revoked), True) + self.assertIs(ocsp._translate_ocsp_query(*openssl_revoked), True) self.assertEqual(mock_log.info.call_count, 0) - self.assertEqual(ocsp._translate_ocsp_query(*openssl_expired_ocsp_revoked), True) + self.assertIs(ocsp._translate_ocsp_query(*openssl_expired_ocsp_revoked), True) self.assertEqual(mock_log.info.call_count, 1) @@ -236,17 +236,17 @@ class OSCPTestCryptography(unittest.TestCase): with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, http_status_code=400): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # OCSP response in invalid with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.UNAUTHORIZED): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # OCSP response is valid, but certificate status is unknown with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # The OCSP response says that the certificate is revoked, but certificate # does not contain the OCSP extension. @@ -255,32 +255,32 @@ class OSCPTestCryptography(unittest.TestCase): side_effect=x509.ExtensionNotFound( 'Not found', x509.AuthorityInformationAccessOID.OCSP)): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # OCSP response uses an unsupported signature. with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=UnsupportedAlgorithm('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # OSCP signature response is invalid. with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=InvalidSignature('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # Assertion error on OCSP response validity with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=AssertionError('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # No responder cert in OCSP response with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks: mocks['mock_response'].return_value.certificates = [] revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) # Responder cert is not signed by certificate issuer with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, @@ -289,7 +289,7 @@ class OSCPTestCryptography(unittest.TestCase): mocks['mock_response'].return_value.certificates[0] = mock.Mock( issuer='fake', subject=cert.subject) revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): # This mock is necessary to avoid the first call contained in _determine_ocsp_server @@ -300,7 +300,7 @@ class OSCPTestCryptography(unittest.TestCase): side_effect=x509.ExtensionNotFound( 'Not found', x509.AuthorityInformationAccessOID.OCSP)): revoked = self.checker.ocsp_revoked(self.cert_obj) - self.assertFalse(revoked) + self.assertIs(revoked, False) @contextlib.contextmanager diff --git a/certbot/tests/plugins/common_test.py b/certbot/tests/plugins/common_test.py index 7de3134fa..6eb5dbfce 100644 --- a/certbot/tests/plugins/common_test.py +++ b/certbot/tests/plugins/common_test.py @@ -174,7 +174,7 @@ class InstallerTest(test_util.ConfigTestCase): def test_current_file_hash_in_all_hashes(self): from certbot._internal.constants import ALL_SSL_DHPARAMS_HASHES - self.assertTrue(self._current_ssl_dhparams_hash() in ALL_SSL_DHPARAMS_HASHES, + self.assertIn(self._current_ssl_dhparams_hash(), ALL_SSL_DHPARAMS_HASHES, "Constants.ALL_SSL_DHPARAMS_HASHES must be appended" " with the sha256 hash of self.config.ssl_dhparams when it is updated.") @@ -330,7 +330,7 @@ class InstallVersionControlledFileTest(test_util.TempDirTestCase): mod_ssl_conf.write("a new line for the wrong hash\n") with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertFalse(mock_logger.warning.called) + self.assertIs(mock_logger.warning.called, False) self.assertTrue(os.path.isfile(self.dest_path)) self.assertEqual(crypto_util.sha256sum(self.source_path), self._current_file_hash()) @@ -352,7 +352,7 @@ class InstallVersionControlledFileTest(test_util.TempDirTestCase): # only print warning once with mock.patch("certbot.plugins.common.logger") as mock_logger: self._call() - self.assertFalse(mock_logger.warning.called) + self.assertIs(mock_logger.warning.called, False) if __name__ == "__main__": unittest.main() # pragma: no cover diff --git a/certbot/tests/plugins/disco_test.py b/certbot/tests/plugins/disco_test.py index 1d3fec722..83dfb41ca 100644 --- a/certbot/tests/plugins/disco_test.py +++ b/certbot/tests/plugins/disco_test.py @@ -75,7 +75,7 @@ class PluginEntryPointTest(unittest.TestCase): name, PluginEntryPoint.entry_point_to_plugin_name(entry_point, with_prefix=True)) def test_description(self): - self.assertTrue("temporary webserver" in self.plugin_ep.description) + self.assertIn("temporary webserver", self.plugin_ep.description) def test_description_with_name(self): self.plugin_ep.plugin_cls = mock.MagicMock(description="Desc") @@ -101,31 +101,31 @@ class PluginEntryPointTest(unittest.TestCase): interfaces.IInstaller, interfaces.IAuthenticator))) def test__init__(self): - self.assertFalse(self.plugin_ep.initialized) - self.assertFalse(self.plugin_ep.prepared) - self.assertFalse(self.plugin_ep.misconfigured) - self.assertFalse(self.plugin_ep.available) - self.assertTrue(self.plugin_ep.problem is None) - self.assertTrue(self.plugin_ep.entry_point is EP_SA) + self.assertIs(self.plugin_ep.initialized, False) + self.assertIs(self.plugin_ep.prepared, False) + self.assertIs(self.plugin_ep.misconfigured, False) + self.assertIs(self.plugin_ep.available, False) + self.assertIsNone(self.plugin_ep.problem) + self.assertIs(self.plugin_ep.entry_point, EP_SA) self.assertEqual("sa", self.plugin_ep.name) - self.assertTrue(self.plugin_ep.plugin_cls is standalone.Authenticator) + self.assertIs(self.plugin_ep.plugin_cls, standalone.Authenticator) def test_init(self): config = mock.MagicMock() plugin = self.plugin_ep.init(config=config) - self.assertTrue(self.plugin_ep.initialized) - self.assertTrue(plugin.config is config) + self.assertIs(self.plugin_ep.initialized, True) + self.assertIs(plugin.config, config) # memoize! - self.assertTrue(self.plugin_ep.init() is plugin) - self.assertTrue(plugin.config is config) + self.assertIs(self.plugin_ep.init(), plugin) + self.assertIs(plugin.config, config) # try to give different config - self.assertTrue(self.plugin_ep.init(123) is plugin) - self.assertTrue(plugin.config is config) + self.assertIs(self.plugin_ep.init(123), plugin) + self.assertIs(plugin.config, config) - self.assertFalse(self.plugin_ep.prepared) - self.assertFalse(self.plugin_ep.misconfigured) - self.assertFalse(self.plugin_ep.available) + self.assertIs(self.plugin_ep.prepared, False) + self.assertIs(self.plugin_ep.misconfigured, False) + self.assertIs(self.plugin_ep.available, False) def test_verify(self): iface1 = mock.MagicMock(__name__="iface1") @@ -155,7 +155,7 @@ class PluginEntryPointTest(unittest.TestCase): self.plugin_ep.init(config=config) self.plugin_ep.prepare() self.assertTrue(self.plugin_ep.prepared) - self.assertFalse(self.plugin_ep.misconfigured) + self.assertIs(self.plugin_ep.misconfigured, False) # output doesn't matter that much, just test if it runs str(self.plugin_ep) @@ -165,12 +165,11 @@ class PluginEntryPointTest(unittest.TestCase): plugin.prepare.side_effect = errors.MisconfigurationError # pylint: disable=protected-access self.plugin_ep._initialized = plugin - self.assertTrue(isinstance(self.plugin_ep.prepare(), - errors.MisconfigurationError)) + self.assertIsInstance(self.plugin_ep.prepare(), + errors.MisconfigurationError) self.assertTrue(self.plugin_ep.prepared) self.assertTrue(self.plugin_ep.misconfigured) - self.assertTrue(isinstance(self.plugin_ep.problem, - errors.MisconfigurationError)) + self.assertIsInstance(self.plugin_ep.problem, errors.MisconfigurationError) self.assertTrue(self.plugin_ep.available) def test_prepare_no_installation(self): @@ -178,21 +177,20 @@ class PluginEntryPointTest(unittest.TestCase): plugin.prepare.side_effect = errors.NoInstallationError # pylint: disable=protected-access self.plugin_ep._initialized = plugin - self.assertTrue(isinstance(self.plugin_ep.prepare(), - errors.NoInstallationError)) - self.assertTrue(self.plugin_ep.prepared) - self.assertFalse(self.plugin_ep.misconfigured) - self.assertFalse(self.plugin_ep.available) + self.assertIsInstance(self.plugin_ep.prepare(), errors.NoInstallationError) + self.assertIs(self.plugin_ep.prepared, True) + self.assertIs(self.plugin_ep.misconfigured, False) + self.assertIs(self.plugin_ep.available, False) def test_prepare_generic_plugin_error(self): plugin = mock.MagicMock() plugin.prepare.side_effect = errors.PluginError # pylint: disable=protected-access self.plugin_ep._initialized = plugin - self.assertTrue(isinstance(self.plugin_ep.prepare(), errors.PluginError)) + self.assertIsInstance(self.plugin_ep.prepare(), errors.PluginError) self.assertTrue(self.plugin_ep.prepared) - self.assertFalse(self.plugin_ep.misconfigured) - self.assertFalse(self.plugin_ep.available) + self.assertIs(self.plugin_ep.misconfigured, False) + self.assertIs(self.plugin_ep.available, False) def test_repr(self): self.assertEqual("PluginEntryPoint#sa", repr(self.plugin_ep)) @@ -226,14 +224,14 @@ class PluginsRegistryTest(unittest.TestCase): standalone.Authenticator, webroot.Authenticator, null.Installer, null.Installer] plugins = PluginsRegistry.find_all() - self.assertTrue(plugins["sa"].plugin_cls is standalone.Authenticator) - self.assertTrue(plugins["sa"].entry_point is EP_SA) - self.assertTrue(plugins["wr"].plugin_cls is webroot.Authenticator) - self.assertTrue(plugins["wr"].entry_point is EP_WR) - self.assertTrue(plugins["ep1"].plugin_cls is null.Installer) - self.assertTrue(plugins["ep1"].entry_point is self.ep1) - self.assertTrue(plugins["p1:ep1"].plugin_cls is null.Installer) - self.assertTrue(plugins["p1:ep1"].entry_point is self.ep1) + self.assertIs(plugins["sa"].plugin_cls, standalone.Authenticator) + self.assertIs(plugins["sa"].entry_point, EP_SA) + self.assertIs(plugins["wr"].plugin_cls, webroot.Authenticator) + self.assertIs(plugins["wr"].entry_point, EP_WR) + self.assertIs(plugins["ep1"].plugin_cls, null.Installer) + self.assertIs(plugins["ep1"].entry_point, self.ep1) + self.assertIs(plugins["p1:ep1"].plugin_cls, null.Installer) + self.assertIs(plugins["p1:ep1"].entry_point, self.ep1) def test_getitem(self): self.assertEqual(self.plugin_ep, self.reg["mock"]) @@ -296,10 +294,10 @@ class PluginsRegistryTest(unittest.TestCase): self.assertEqual({}, self.reg.available()._plugins) def test_find_init(self): - self.assertTrue(self.reg.find_init(mock.Mock()) is None) + self.assertIsNone(self.reg.find_init(mock.Mock())) self.plugin_ep.initialized = True - self.assertTrue( - self.reg.find_init(self.plugin_ep.init()) is self.plugin_ep) + self.assertIs( + self.reg.find_init(self.plugin_ep.init()), self.plugin_ep) def test_repr(self): self.plugin_ep.__repr__ = lambda _: "PluginEntryPoint#mock" diff --git a/certbot/tests/plugins/dns_common_test.py b/certbot/tests/plugins/dns_common_test.py index 377244c4c..12fac00d0 100644 --- a/certbot/tests/plugins/dns_common_test.py +++ b/certbot/tests/plugins/dns_common_test.py @@ -211,20 +211,20 @@ class CredentialsConfigurationRequireTest(test_util.TempDirTestCase): class DomainNameGuessTest(unittest.TestCase): def test_simple_case(self): - self.assertTrue( - 'example.com' in + self.assertIn( + 'example.com', dns_common.base_domain_name_guesses("example.com") ) def test_sub_domain(self): - self.assertTrue( - 'example.com' in + self.assertIn( + 'example.com', dns_common.base_domain_name_guesses("foo.bar.baz.example.com") ) def test_second_level_domain(self): - self.assertTrue( - 'example.co.uk' in + self.assertIn( + 'example.co.uk', dns_common.base_domain_name_guesses("foo.bar.baz.example.co.uk") ) diff --git a/certbot/tests/plugins/manual_test.py b/certbot/tests/plugins/manual_test.py index 08ab20456..c97e08fa6 100644 --- a/certbot/tests/plugins/manual_test.py +++ b/certbot/tests/plugins/manual_test.py @@ -52,7 +52,7 @@ class AuthenticatorTest(test_util.TempDirTestCase): self.assertRaises(errors.HookCommandNotFound, self.auth.prepare) def test_more_info(self): - self.assertTrue(isinstance(self.auth.more_info(), str)) + self.assertIsInstance(self.auth.more_info(), str) def test_get_chall_pref(self): self.assertEqual(self.auth.get_chall_pref('example.org'), @@ -96,9 +96,8 @@ class AuthenticatorTest(test_util.TempDirTestCase): [achall.response(achall.account_key) for achall in self.achalls]) for i, (args, kwargs) in enumerate(mock_get_utility().notification.call_args_list): achall = self.achalls[i] - self.assertTrue( - achall.validation(achall.account_key) in args[0]) - self.assertFalse(kwargs['wrap']) + self.assertIn(achall.validation(achall.account_key), args[0]) + self.assertIs(kwargs['wrap'], False) def test_cleanup(self): self.config.manual_auth_hook = ('{0} -c "import sys; sys.stdout.write(\'foo\')"' @@ -119,7 +118,7 @@ class AuthenticatorTest(test_util.TempDirTestCase): os.environ['CERTBOT_TOKEN'], achall.chall.encode('token')) else: - self.assertFalse('CERTBOT_TOKEN' in os.environ) + self.assertNotIn('CERTBOT_TOKEN', os.environ) if __name__ == '__main__': diff --git a/certbot/tests/plugins/null_test.py b/certbot/tests/plugins/null_test.py index dad5b270a..dfdd0a7de 100644 --- a/certbot/tests/plugins/null_test.py +++ b/certbot/tests/plugins/null_test.py @@ -15,7 +15,7 @@ class InstallerTest(unittest.TestCase): self.installer = Installer(config=mock.MagicMock(), name="null") def test_it(self): - self.assertTrue(isinstance(self.installer.more_info(), str)) + self.assertIsInstance(self.installer.more_info(), str) self.assertEqual([], self.installer.get_all_names()) self.assertEqual([], self.installer.supported_enhancements()) diff --git a/certbot/tests/plugins/selection_test.py b/certbot/tests/plugins/selection_test.py index 7fcd213a0..60917626a 100644 --- a/certbot/tests/plugins/selection_test.py +++ b/certbot/tests/plugins/selection_test.py @@ -70,7 +70,7 @@ class PickPluginTest(unittest.TestCase): self.assertEqual(1, self.reg.visible().ifaces.call_count) def test_no_candidate(self): - self.assertTrue(self._call() is None) + self.assertIsNone(self._call()) def test_single(self): plugin_ep = mock.MagicMock() @@ -88,7 +88,7 @@ class PickPluginTest(unittest.TestCase): self.reg.visible().ifaces().verify().available.return_value = { "bar": plugin_ep} - self.assertTrue(self._call() is None) + self.assertIsNone(self._call()) def test_multiple(self): plugin_ep = mock.MagicMock() @@ -111,7 +111,7 @@ class PickPluginTest(unittest.TestCase): with mock.patch("certbot._internal.plugins.selection.choose_plugin") as mock_choose: mock_choose.return_value = None - self.assertTrue(self._call() is None) + self.assertIsNone(self._call()) class ChoosePluginTest(unittest.TestCase): @@ -153,7 +153,7 @@ class ChoosePluginTest(unittest.TestCase): @test_util.patch_get_utility("certbot._internal.plugins.selection.z_util") def test_no_choice(self, mock_util): mock_util().menu.return_value = (display_util.CANCEL, 0) - self.assertTrue(self._call() is None) + self.assertIsNone(self._call()) class GetUnpreparedInstallerTest(test_util.ConfigTestCase): @@ -180,7 +180,7 @@ class GetUnpreparedInstallerTest(test_util.ConfigTestCase): def test_no_installer_defined(self): self.config.configurator = None - self.assertEqual(self._call(), None) + self.assertIsNone(self._call()) def test_no_available_installers(self): self.config.configurator = "apache" @@ -190,7 +190,7 @@ class GetUnpreparedInstallerTest(test_util.ConfigTestCase): def test_get_plugin(self): self.config.configurator = "apache" installer = self._call() - self.assertTrue(installer is self.mock_apache_plugin) + self.assertIs(installer, self.mock_apache_plugin) def test_multiple_installers_returned(self): self.config.configurator = "apache" diff --git a/certbot/tests/plugins/standalone_test.py b/certbot/tests/plugins/standalone_test.py index 5b3fffd9d..6f2ae91ba 100644 --- a/certbot/tests/plugins/standalone_test.py +++ b/certbot/tests/plugins/standalone_test.py @@ -29,9 +29,8 @@ class ServerManagerTest(unittest.TestCase): self.mgr = ServerManager(self.certs, self.http_01_resources) def test_init(self): - self.assertTrue(self.mgr.certs is self.certs) - self.assertTrue( - self.mgr.http_01_resources is self.http_01_resources) + self.assertIs(self.mgr.certs, self.certs) + self.assertIs(self.mgr.http_01_resources, self.http_01_resources) def _test_run_stop(self, challenge_type): server = self.mgr.run(port=0, challenge_type=challenge_type) @@ -48,7 +47,7 @@ class ServerManagerTest(unittest.TestCase): port = server.getsocknames()[0][1] server2 = self.mgr.run(port=port, challenge_type=challenges.HTTP01) self.assertEqual(self.mgr.running(), {port: server}) - self.assertTrue(server is server2) + self.assertIs(server, server2) self.mgr.stop(port) self.assertEqual(self.mgr.running(), {}) @@ -89,7 +88,7 @@ class AuthenticatorTest(unittest.TestCase): self.auth.servers = mock.MagicMock() def test_more_info(self): - self.assertTrue(isinstance(self.auth.more_info(), str)) + self.assertIsInstance(self.auth.more_info(), str) def test_get_chall_pref(self): self.assertEqual(self.auth.get_chall_pref(domain=None), @@ -126,7 +125,7 @@ class AuthenticatorTest(unittest.TestCase): def _assert_correct_yesno_call(self, mock_yesno): yesno_args, yesno_kwargs = mock_yesno.call_args - self.assertTrue("in use" in yesno_args[0]) + self.assertIn("in use", yesno_args[0]) self.assertFalse(yesno_kwargs.get("default", True)) def test_perform_eacces(self): diff --git a/certbot/tests/plugins/storage_test.py b/certbot/tests/plugins/storage_test.py index 36159e44f..d01845510 100644 --- a/certbot/tests/plugins/storage_test.py +++ b/certbot/tests/plugins/storage_test.py @@ -49,7 +49,7 @@ class PluginStorageTest(test_util.ConfigTestCase): self.assertRaises(KeyError, nocontent.storage.fetch, "value") self.assertTrue(mock_log.called) - self.assertTrue("no values loaded" in mock_log.call_args[0][0]) + self.assertIn("no values loaded", mock_log.call_args[0][0]) def test_load_errors_corrupted(self): with open(os.path.join(self.config.config_dir, @@ -61,7 +61,7 @@ class PluginStorageTest(test_util.ConfigTestCase): self.assertRaises(errors.PluginError, corrupted.storage.fetch, "value") - self.assertTrue("is corrupted" in mock_log.call_args[0][0]) + self.assertIn("is corrupted", mock_log.call_args[0][0]) def test_save_errors_cant_serialize(self): with mock.patch("certbot.plugins.storage.logger.error") as mock_log: @@ -71,7 +71,7 @@ class PluginStorageTest(test_util.ConfigTestCase): self.plugin.storage._data = self.plugin_cls # pylint: disable=protected-access self.assertRaises(errors.PluginStorageError, self.plugin.storage.save) - self.assertTrue("Could not serialize" in mock_log.call_args[0][0]) + self.assertIn("Could not serialize", mock_log.call_args[0][0]) def test_save_errors_unable_to_write_file(self): mock_open = mock.mock_open() @@ -83,7 +83,7 @@ class PluginStorageTest(test_util.ConfigTestCase): self.plugin.storage._storagepath = "/tmp/whatever" self.assertRaises(errors.PluginStorageError, self.plugin.storage.save) - self.assertTrue("Could not write" in mock_log.call_args[0][0]) + self.assertIn("Could not write", mock_log.call_args[0][0]) def test_save_uninitialized(self): with mock.patch("certbot.reverter.util"): @@ -114,7 +114,7 @@ class PluginStorageTest(test_util.ConfigTestCase): ".pluginstorage.json"), 'r') as fh: psdata = fh.read() psjson = json.loads(psdata) - self.assertTrue("mockplugin" in psjson.keys()) + self.assertIn("mockplugin", psjson.keys()) self.assertEqual(len(psjson), 1) self.assertEqual(psjson["mockplugin"]["testkey"], "testvalue") diff --git a/certbot/tests/plugins/util_test.py b/certbot/tests/plugins/util_test.py index 9387b4ae7..1b4fcd652 100644 --- a/certbot/tests/plugins/util_test.py +++ b/certbot/tests/plugins/util_test.py @@ -30,7 +30,7 @@ class PathSurgeryTest(unittest.TestCase): with mock.patch.dict('os.environ', all_path): with mock.patch('certbot.util.exe_exists') as mock_exists: mock_exists.return_value = True - self.assertEqual(path_surgery("eg"), True) + self.assertIs(path_surgery("eg"), True) self.assertEqual(mock_debug.call_count, 0) self.assertEqual(os.environ["PATH"], all_path["PATH"]) if os.name != 'nt': @@ -39,9 +39,9 @@ class PathSurgeryTest(unittest.TestCase): with mock.patch.dict('os.environ', no_path): path_surgery("thingy") self.assertEqual(mock_debug.call_count, 2 if os.name != 'nt' else 1) - self.assertTrue("Failed to find" in mock_debug.call_args[0][0]) - self.assertTrue("/usr/local/bin" in os.environ["PATH"]) - self.assertTrue("/tmp" in os.environ["PATH"]) + self.assertIn("Failed to find", mock_debug.call_args[0][0]) + self.assertIn("/usr/local/bin", os.environ["PATH"]) + self.assertIn("/tmp", os.environ["PATH"]) if __name__ == "__main__": diff --git a/certbot/tests/plugins/webroot_test.py b/certbot/tests/plugins/webroot_test.py index 5792924a9..f158486b6 100644 --- a/certbot/tests/plugins/webroot_test.py +++ b/certbot/tests/plugins/webroot_test.py @@ -58,8 +58,8 @@ class AuthenticatorTest(unittest.TestCase): def test_more_info(self): more_info = self.auth.more_info() - self.assertTrue(isinstance(more_info, str)) - self.assertTrue(self.path in more_info) + self.assertIsInstance(more_info, str) + self.assertIn(self.path, more_info) def test_add_parser_arguments(self): add = mock.MagicMock() @@ -79,7 +79,7 @@ class AuthenticatorTest(unittest.TestCase): self.auth.perform([self.achall]) self.assertTrue(mock_display.menu.called) for call in mock_display.menu.call_args_list: - self.assertTrue(self.achall.domain in call[0][0]) + self.assertIn(self.achall.domain, call[0][0]) self.assertTrue(all( webroot in call[0][1] for webroot in self.config.webroot_map.values())) @@ -96,7 +96,7 @@ class AuthenticatorTest(unittest.TestCase): self.assertRaises(errors.PluginError, self.auth.perform, [self.achall]) self.assertTrue(mock_display.menu.called) for call in mock_display.menu.call_args_list: - self.assertTrue(self.achall.domain in call[0][0]) + self.assertIn(self.achall.domain, call[0][0]) self.assertTrue(all( webroot in call[0][1] for webroot in self.config.webroot_map.values())) diff --git a/certbot/tests/renewal_test.py b/certbot/tests/renewal_test.py index 7c9c53fb4..edee8df6c 100644 --- a/certbot/tests/renewal_test.py +++ b/certbot/tests/renewal_test.py @@ -115,7 +115,7 @@ class RenewalTest(test_util.ConfigTestCase): renewal_candidate = renewal._reconstitute(lineage_config, rc_path) # This means that manual_public_ip_logging_ok was not modified in the config based on its # value in the renewal conf file - self.assertTrue(isinstance(lineage_config.manual_public_ip_logging_ok, mock.MagicMock)) + self.assertIsInstance(lineage_config.manual_public_ip_logging_ok, mock.MagicMock) class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): @@ -129,7 +129,7 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): def test_allow_subset_of_names_success(self, mock_set_by_cli): mock_set_by_cli.return_value = False self._call(self.config, {'allow_subset_of_names': 'True'}) - self.assertTrue(self.config.allow_subset_of_names is True) + self.assertIs(self.config.allow_subset_of_names, True) @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_allow_subset_of_names_failure(self, mock_set_by_cli): @@ -164,7 +164,7 @@ class RestoreRequiredConfigElementsTest(test_util.ConfigTestCase): def test_must_staple_success(self, mock_set_by_cli): mock_set_by_cli.return_value = False self._call(self.config, {'must_staple': 'True'}) - self.assertTrue(self.config.must_staple is True) + self.assertIs(self.config.must_staple, True) @mock.patch('certbot._internal.renewal.cli.set_by_cli') def test_must_staple_failure(self, mock_set_by_cli): diff --git a/certbot/tests/renewupdater_test.py b/certbot/tests/renewupdater_test.py index 5137c81c3..55faff2a4 100644 --- a/certbot/tests/renewupdater_test.py +++ b/certbot/tests/renewupdater_test.py @@ -42,7 +42,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): mock_generic_updater.generic_updates.reset_mock() updater.run_generic_updaters(self.config, mock.MagicMock(), None) self.assertEqual(mock_generic_updater.generic_updates.call_count, 1) - self.assertFalse(mock_generic_updater.restart.called) + self.assertIs(mock_generic_updater.restart.called, False) def test_renew_deployer(self): lineage = mock.MagicMock() @@ -83,13 +83,13 @@ class RenewUpdaterTest(test_util.ConfigTestCase): self.config.disable_renew_updates = True mock_geti.return_value = self.mockinstaller updater.run_generic_updaters(self.config, mock.MagicMock(), None) - self.assertFalse(self.mockinstaller.update_autohsts.called) + self.assertIs(self.mockinstaller.update_autohsts.called, False) def test_enhancement_deployer_not_called(self): self.config.disable_renew_updates = True updater.run_renewal_deployer(self.config, mock.MagicMock(), self.mockinstaller) - self.assertFalse(self.mockinstaller.deploy_autohsts.called) + self.assertIs(self.mockinstaller.deploy_autohsts.called, False) @mock.patch('certbot._internal.plugins.selection.get_unprepared_installer') def test_enhancement_no_updater(self, mock_geti): @@ -105,7 +105,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): mock_geti.return_value = self.mockinstaller with mock.patch("certbot.plugins.enhancements._INDEX", FAKEINDEX): updater.run_generic_updaters(self.config, mock.MagicMock(), None) - self.assertFalse(self.mockinstaller.update_autohsts.called) + self.assertIs(self.mockinstaller.update_autohsts.called, False) def test_enhancement_no_deployer(self): FAKEINDEX = [ @@ -120,7 +120,7 @@ class RenewUpdaterTest(test_util.ConfigTestCase): with mock.patch("certbot.plugins.enhancements._INDEX", FAKEINDEX): updater.run_renewal_deployer(self.config, mock.MagicMock(), self.mockinstaller) - self.assertFalse(self.mockinstaller.deploy_autohsts.called) + self.assertIs(self.mockinstaller.deploy_autohsts.called, False) if __name__ == '__main__': diff --git a/certbot/tests/reporter_test.py b/certbot/tests/reporter_test.py index 7a37f782e..c4af40591 100644 --- a/certbot/tests/reporter_test.py +++ b/certbot/tests/reporter_test.py @@ -26,8 +26,8 @@ class ReporterTest(unittest.TestCase): self.reporter.add_message("Line 1\nLine 2", self.reporter.LOW_PRIORITY) self.reporter.print_messages() output = sys.stdout.getvalue() # type: ignore - self.assertTrue("Line 1\n" in output) - self.assertTrue("Line 2" in output) + self.assertIn("Line 1\n", output) + self.assertIn("Line 2", output) def test_tty_print_empty(self): sys.stdout.isatty = lambda: True # type: ignore @@ -60,10 +60,10 @@ class ReporterTest(unittest.TestCase): self._add_messages() self.reporter.print_messages() output = sys.stdout.getvalue() # type: ignore - self.assertTrue("IMPORTANT NOTES:" in output) - self.assertTrue("High" in output) - self.assertTrue("Med" in output) - self.assertTrue("Low" in output) + self.assertIn("IMPORTANT NOTES:", output) + self.assertIn("High", output) + self.assertIn("Med", output) + self.assertIn("Low", output) def _unsuccessful_exit_common(self): self._add_messages() @@ -72,10 +72,10 @@ class ReporterTest(unittest.TestCase): except ValueError: self.reporter.print_messages() output = sys.stdout.getvalue() # type: ignore - self.assertTrue("IMPORTANT NOTES:" in output) - self.assertTrue("High" in output) - self.assertTrue("Med" not in output) - self.assertTrue("Low" not in output) + self.assertIn("IMPORTANT NOTES:", output) + self.assertIn("High", output) + self.assertNotIn("Med", output) + self.assertNotIn("Low", output) def _add_messages(self): self.reporter.add_message("High", self.reporter.HIGH_PRIORITY) diff --git a/certbot/tests/reverter_test.py b/certbot/tests/reverter_test.py index 45479b16d..e8d85d4d1 100644 --- a/certbot/tests/reverter_test.py +++ b/certbot/tests/reverter_test.py @@ -48,7 +48,7 @@ class ReverterCheckpointLocalTest(test_util.ConfigTestCase): no_change = os.path.join(self.reverter.config.backup_dir, path, "CHANGES_SINCE") with open(no_change, "r") as f: x = f.read() - self.assertTrue("No changes" in x) + self.assertIn("No changes", x) def test_basic_add_to_temp_checkpoint(self): # These shouldn't conflict even though they are both named config.txt @@ -328,8 +328,8 @@ class TestFullCheckpointsReverter(test_util.ConfigTestCase): # One dir left... check title all_dirs = os.listdir(self.config.backup_dir) self.assertEqual(len(all_dirs), 1) - self.assertTrue( - "First Checkpoint" in get_save_notes( + self.assertIn( + "First Checkpoint", get_save_notes( os.path.join(self.config.backup_dir, all_dirs[0]))) # Final rollback self.reverter.rollback_checkpoints(1) diff --git a/certbot/tests/storage_test.py b/certbot/tests/storage_test.py index d7ef24b43..aa5910f1e 100644 --- a/certbot/tests/storage_test.py +++ b/certbot/tests/storage_test.py @@ -195,11 +195,11 @@ class RenewableCertTests(BaseRenewableCertTest): from certbot._internal import storage self._write_out_ex_kinds() - self.assertTrue("version" not in self.config_file) + self.assertNotIn("version", self.config_file) with mock.patch("certbot._internal.storage.logger") as mock_logger: storage.RenewableCert(self.config_file.filename, self.config) - self.assertFalse(mock_logger.warning.called) + self.assertIs(mock_logger.warning.called, False) def test_renewal_newer_version(self): from certbot._internal import storage @@ -211,7 +211,7 @@ class RenewableCertTests(BaseRenewableCertTest): with mock.patch("certbot._internal.storage.logger") as mock_logger: storage.RenewableCert(self.config_file.filename, self.config) self.assertTrue(mock_logger.info.called) - self.assertTrue("version" in mock_logger.info.call_args[0][0]) + self.assertIn("version", mock_logger.info.call_args[0][0]) def test_consistent(self): # pylint: disable=protected-access @@ -282,7 +282,7 @@ class RenewableCertTests(BaseRenewableCertTest): self.assertEqual(self.test_rc.current_version("cert"), 10) def test_no_current_version(self): - self.assertEqual(self.test_rc.current_version("cert"), None) + self.assertIsNone(self.test_rc.current_version("cert")) def test_latest_and_next_versions(self): for ver in range(1, 6): @@ -314,12 +314,12 @@ class RenewableCertTests(BaseRenewableCertTest): self.test_rc.latest_common_version = mock.Mock() mock_has_pending.return_value = False - self.assertEqual(self.test_rc.ensure_deployed(), True) + self.assertIs(self.test_rc.ensure_deployed(), True) self.assertEqual(mock_update.call_count, 0) self.assertEqual(mock_logger.warning.call_count, 0) mock_has_pending.return_value = True - self.assertEqual(self.test_rc.ensure_deployed(), False) + self.assertIs(self.test_rc.ensure_deployed(), False) self.assertEqual(mock_update.call_count, 1) self.assertEqual(mock_logger.warning.call_count, 1) @@ -586,7 +586,7 @@ class RenewableCertTests(BaseRenewableCertTest): self._write_out_kind(kind, 1) self.test_rc.update_all_links_to(1) self.test_rc.save_successor(1, b"newcert", None, b"new chain", self.config) - self.assertFalse(mock_ownership.called) + self.assertIs(mock_ownership.called, False) self.test_rc.save_successor(2, b"newcert", b"new_privkey", b"new chain", self.config) self.assertTrue(mock_ownership.called) @@ -767,7 +767,7 @@ class RenewableCertTests(BaseRenewableCertTest): def test_server(self): self.test_rc.configuration["renewalparams"] = {} - self.assertEqual(self.test_rc.server, None) + self.assertIsNone(self.test_rc.server) rp = self.test_rc.configuration["renewalparams"] rp["server"] = "https://acme.example/dir" self.assertEqual(self.test_rc.server, "https://acme.example/dir") @@ -775,15 +775,15 @@ class RenewableCertTests(BaseRenewableCertTest): def test_is_test_cert(self): self.test_rc.configuration["renewalparams"] = {} rp = self.test_rc.configuration["renewalparams"] - self.assertEqual(self.test_rc.is_test_cert, False) + self.assertIs(self.test_rc.is_test_cert, False) rp["server"] = "https://acme-staging-v02.api.letsencrypt.org/directory" - self.assertEqual(self.test_rc.is_test_cert, True) + self.assertIs(self.test_rc.is_test_cert, True) rp["server"] = "https://staging.someotherca.com/directory" - self.assertEqual(self.test_rc.is_test_cert, True) + self.assertIs(self.test_rc.is_test_cert, True) rp["server"] = "https://acme-v01.api.letsencrypt.org/directory" - self.assertEqual(self.test_rc.is_test_cert, False) + self.assertIs(self.test_rc.is_test_cert, False) rp["server"] = "https://acme-v02.api.letsencrypt.org/directory" - self.assertEqual(self.test_rc.is_test_cert, False) + self.assertIs(self.test_rc.is_test_cert, False) def test_missing_cert(self): from certbot._internal import storage @@ -817,13 +817,13 @@ class RenewableCertTests(BaseRenewableCertTest): with open(temp2, "r") as f: content = f.read() # useful value was updated - self.assertTrue("useful = new_value" in content) + self.assertIn("useful = new_value", content) # associated comment was preserved - self.assertTrue("A useful value" in content) + self.assertIn("A useful value", content) # useless value was deleted - self.assertTrue("useless" not in content) + self.assertNotIn("useless", content) # check version was stored - self.assertTrue("version = {0}".format(certbot.__version__) in content) + self.assertIn("version = {0}".format(certbot.__version__), content) # ensure permissions are copied self.assertEqual(stat.S_IMODE(os.lstat(temp).st_mode), stat.S_IMODE(os.lstat(temp2).st_mode)) diff --git a/certbot/tests/util_test.py b/certbot/tests/util_test.py index e2f0218b8..a78b614cf 100644 --- a/certbot/tests/util_test.py +++ b/certbot/tests/util_test.py @@ -260,7 +260,7 @@ class UniqueLineageNameTest(test_util.TempDirTestCase): def test_basic(self): f, path = self._call("wow") - self.assertTrue(isinstance(f, file_type)) + self.assertIsInstance(f, file_type) self.assertEqual(os.path.join(self.tempdir, "wow.conf"), path) f.close() @@ -269,9 +269,9 @@ class UniqueLineageNameTest(test_util.TempDirTestCase): for _ in range(10): items.append(self._call("wow")) f, name = items[-1] - self.assertTrue(isinstance(f, file_type)) - self.assertTrue(isinstance(name, str)) - self.assertTrue("wow-0009.conf" in name) + self.assertIsInstance(f, file_type) + self.assertIsInstance(name, str) + self.assertIn("wow-0009.conf", name) for f, _ in items: f.close() @@ -349,7 +349,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase): with mock.patch("certbot.util.logger.warning") as mock_warn: self.parser.parse_args(["--old-option"]) self.assertEqual(mock_warn.call_count, 1) - self.assertTrue("is deprecated" in mock_warn.call_args[0][0]) + self.assertIn("is deprecated", mock_warn.call_args[0][0]) self.assertEqual("--old-option", mock_warn.call_args[0][1]) def test_warning_with_arg(self): @@ -357,7 +357,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase): with mock.patch("certbot.util.logger.warning") as mock_warn: self.parser.parse_args(["--old-option", "42"]) self.assertEqual(mock_warn.call_count, 1) - self.assertTrue("is deprecated" in mock_warn.call_args[0][0]) + self.assertIn("is deprecated", mock_warn.call_args[0][0]) self.assertEqual("--old-option", mock_warn.call_args[0][1]) def test_help(self): @@ -368,7 +368,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase): self.parser.parse_args(["-h"]) except SystemExit: pass - self.assertTrue("--old-option" not in stdout.getvalue()) + self.assertNotIn("--old-option", stdout.getvalue()) def test_set_constant(self): """Test when ACTION_TYPES_THAT_DONT_NEED_A_VALUE is a set. @@ -519,7 +519,7 @@ class OsInfoTest(unittest.TestCase): m_distro.like.return_value = "first debian third" id_likes = cbutil.get_systemd_os_like() self.assertEqual(len(id_likes), 3) - self.assertTrue("debian" in id_likes) + self.assertIn("debian", id_likes) @mock.patch("certbot.util.distro") @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") @@ -610,7 +610,7 @@ class AtexitRegisterTest(unittest.TestCase): def test_not_called(self): self._test_common(initial_pid=-1) - self.assertFalse(self.func.called) + self.assertIs(self.func.called, False) def _test_common(self, initial_pid): with mock.patch('certbot.util._INITIAL_PID', initial_pid): From d3d9a05826af027b31de5cb60948dafbf6597873 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 3 May 2021 12:38:54 -0700 Subject: [PATCH 06/16] fix client email address (#8817) client-dev@letsencrypt.org is no longer used by the Certbot team so this PR updates the email address in our packages to our current mailing list. --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-ci/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/setup.py | 2 +- windows-installer/setup.py | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 443aab6e8..2e2eb6a6d 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -37,7 +37,7 @@ setup( description='ACME protocol implementation in Python', url='https://github.com/letsencrypt/letsencrypt', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 76ebbddfd..efc9ea38a 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -24,7 +24,7 @@ setup( description="Apache plugin for Certbot", url='https://github.com/letsencrypt/letsencrypt', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-ci/setup.py b/certbot-ci/setup.py index ad7672e17..9d52b6268 100644 --- a/certbot-ci/setup.py +++ b/certbot-ci/setup.py @@ -38,7 +38,7 @@ setup( description="Certbot continuous integration framework", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index f1bf28596..51d555fbb 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -24,7 +24,7 @@ setup( description="Compatibility tests for Certbot", url='https://github.com/letsencrypt/letsencrypt', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index fcc7c3036..b9c0244fb 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -36,7 +36,7 @@ setup( description="Cloudflare DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 6452d325d..b3185a32d 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -36,7 +36,7 @@ setup( description="CloudXNS DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 33f16314e..656800f72 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -36,7 +36,7 @@ setup( description="DigitalOcean DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 14fcd4a69..09713b928 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -47,7 +47,7 @@ setup( description="DNSimple DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index dd02d96b5..18bff0761 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -36,7 +36,7 @@ setup( description="DNS Made Easy DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 00ff0834a..8d8656fdc 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -35,7 +35,7 @@ setup( description="Gehirn Infrastructure Service DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 4933ffb0b..b7e984f2b 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -39,7 +39,7 @@ setup( description="Google Cloud DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 55dad1d60..372e2d5dd 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -35,7 +35,7 @@ setup( description="Linode DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 46c71c46b..5136ed274 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -36,7 +36,7 @@ setup( description="LuaDNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index 6d3218221..e9e1a53b0 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -36,7 +36,7 @@ setup( description="NS1 DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index e8e44db30..c6c27bdd6 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -36,7 +36,7 @@ setup( description="OVH DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 6b4648d91..39315c866 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -36,7 +36,7 @@ setup( description="RFC 2136 DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 30c45dc84..afff18efa 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -36,7 +36,7 @@ setup( description="Route53 DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index c328429c9..bbd85944f 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -35,7 +35,7 @@ setup( description="Sakura Cloud DNS Authenticator plugin for Certbot", url='https://github.com/certbot/certbot', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 11df5eddf..740218449 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -20,7 +20,7 @@ setup( description="Nginx plugin for Certbot", url='https://github.com/letsencrypt/letsencrypt', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/certbot/setup.py b/certbot/setup.py index 6913d8384..e0078bd6e 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -100,7 +100,7 @@ setup( long_description=readme, url='https://github.com/letsencrypt/letsencrypt', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ diff --git a/windows-installer/setup.py b/windows-installer/setup.py index d5b4d2bde..cddc9ea18 100644 --- a/windows-installer/setup.py +++ b/windows-installer/setup.py @@ -9,7 +9,7 @@ setup( description='Environment to build the Certbot Windows installer', url='https://github.com/letsencrypt/letsencrypt', author="Certbot Project", - author_email='client-dev@letsencrypt.org', + author_email='certbot-dev@eff.org', license='Apache License 2.0', python_requires='>=3.6', classifiers=[ From dd0e590de3095097832051756d13850bf1561d8e Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 3 May 2021 17:42:30 -0700 Subject: [PATCH 07/16] Make a test farm tests package (#8821) Fixes https://github.com/certbot/certbot/issues/8781. This PR makes our test farm tests into a normal package so it and its dependencies can be tracked and installed like our other packages. Other noteworthy changes in this PR: * Rather than continuing to place logs in your CWD, they're placed in a temporary directory that is printed to the terminal. * `tests/letstest/auto_targets.yaml` was deleted rather than renamed because the file is no longer used. * make a letstest package * remove deleted deps * fix letstest install * add __init__.py * call main * Explicitly mention activating venv * rerename file * fix version.py path * clarify "this" * Use >= instead of caret requirement --- .gitignore | 6 -- {tests/letstest => letstest}/README.md | 22 +++---- letstest/letstest/__init__.py | 0 {tests => letstest}/letstest/multitester.py | 8 +-- .../scripts/bootstrap_os_packages.sh | 0 .../scripts/test_apache2.sh | 4 +- .../scripts/test_openssl_version.py | 0 .../scripts/test_sdists.sh | 4 +- .../letstest => letstest}/scripts/version.py | 4 +- letstest/setup.py | 45 ++++++++++++++ .../targets}/apache2_targets.yaml | 0 .../targets}/targets.yaml | 0 tests/letstest/auto_targets.yaml | 59 ------------------- tests/letstest/requirements.txt | 22 ------- tools/_release.sh | 4 +- tools/pinning/pyproject.toml | 9 +++ tools/requirements.txt | 40 +++++++------ tools/venv.py | 1 + tox.ini | 16 +++-- 19 files changed, 108 insertions(+), 136 deletions(-) rename {tests/letstest => letstest}/README.md (74%) create mode 100644 letstest/letstest/__init__.py rename {tests => letstest}/letstest/multitester.py (98%) rename {tests/letstest => letstest}/scripts/bootstrap_os_packages.sh (100%) rename {tests/letstest => letstest}/scripts/test_apache2.sh (96%) rename {tests/letstest => letstest}/scripts/test_openssl_version.py (100%) rename {tests/letstest => letstest}/scripts/test_sdists.sh (92%) rename {tests/letstest => letstest}/scripts/version.py (85%) create mode 100644 letstest/setup.py rename {tests/letstest => letstest/targets}/apache2_targets.yaml (100%) rename {tests/letstest => letstest/targets}/targets.yaml (100%) delete mode 100644 tests/letstest/auto_targets.yaml delete mode 100644 tests/letstest/requirements.txt diff --git a/.gitignore b/.gitignore index a50dddc06..285e68a42 100644 --- a/.gitignore +++ b/.gitignore @@ -30,12 +30,6 @@ tags # auth --cert-path --chain-path /*.pem -# letstest -tests/letstest/letest-*/ -tests/letstest/*.pem -tests/letstest/venv/ -tests/letstest/venv3/ - .venv # pytest cache diff --git a/tests/letstest/README.md b/letstest/README.md similarity index 74% rename from tests/letstest/README.md rename to letstest/README.md index aea4e2e13..c569d1e8f 100644 --- a/tests/letstest/README.md +++ b/letstest/README.md @@ -14,17 +14,13 @@ Simple AWS testfarm scripts for certbot client testing are needed, they need to be requested via online webform. ## Installation and configuration -These tests require Python 3, awscli, boto3, PyYAML, and fabric 2.0+. If you're -on a Debian based system, make sure you also have the python3-venv package -installed. If you have Python 3 installed, you can use requirements.txt to -create a virtual environment with a known set of dependencies by running: -``` -python3 -m venv venv3 -. ./venv3/bin/activate -pip install --requirement requirements.txt -``` -You can then configure AWS credentials and create a key by running: +This package is installed in the Certbot development environment that is +created by following the instructions at +https://certbot.eff.org/docs/contributing.html#running-a-local-copy-of-the-client. + +After activating that virtual environment, you can then configure AWS +credentials and create a key by running: ``` >aws configure --profile [interactive: enter secrets for IAM role] @@ -35,9 +31,9 @@ Note: whatever you pick for `` will be shown to other users with AWS a When prompted for a default region name, enter: `us-east-1`. ## Usage -To run tests, activate the virtual environment you created above and run: +To run tests, activate the virtual environment you created above and from this directory run: ``` ->python multitester.py targets.yaml /path/to/your/key.pem scripts/ +>letstest targets/targets.yaml /path/to/your/key.pem scripts/ ``` You can only run up to two tests at once. The following error is often indicative of there being too many AWS instances running on our account: @@ -52,7 +48,7 @@ aws ec2 terminate-instances --profile --instance-ids $(aws ec2 de It will take a minute for these instances to shut down and become available again. Running this will invalidate any in progress tests. -A folder named `letest-` is also created with a log file from each instance of the test and a file named "results" containing the output above. +A temporary directory whose name is output by the tests is also created with a log file from each instance of the test and a file named "results" containing the output above. The tests take quite a while to run. ## Scripts diff --git a/letstest/letstest/__init__.py b/letstest/letstest/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/letstest/multitester.py b/letstest/letstest/multitester.py similarity index 98% rename from tests/letstest/multitester.py rename to letstest/letstest/multitester.py index 360bb979e..a56bf0f37 100644 --- a/tests/letstest/multitester.py +++ b/letstest/letstest/multitester.py @@ -22,7 +22,7 @@ Usage: >aws ec2 create-key-pair --profile HappyHacker --key-name MyKeyPair \ --query 'KeyMaterial' --output text > MyKeyPair.pem then: ->python multitester.py targets.yaml MyKeyPair.pem HappyHacker scripts/test_sdists.sh +>letstest targets/targets.yaml MyKeyPair.pem HappyHacker scripts/test_sdists.sh see: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html https://docs.aws.amazon.com/cli/latest/userguide/cli-ec2-keypairs.html @@ -33,6 +33,7 @@ from multiprocessing import Manager import os import socket import sys +import tempfile import time import traceback import urllib.error as urllib_error @@ -374,9 +375,8 @@ def main(): # Set up local copy of git repo #------------------------------------------------------------------------------- - log_dir = "letest-%d"%int(time.time()) #points to logging / working directory - print("Making local dir for test repo and logs: %s"%log_dir) - local_cxn.local('mkdir %s'%log_dir) + log_dir = tempfile.mkdtemp() # points to logging / working directory + print("Local dir for test repo and logs: %s"%log_dir) try: # figure out what git object to test and locally create it in log_dir diff --git a/tests/letstest/scripts/bootstrap_os_packages.sh b/letstest/scripts/bootstrap_os_packages.sh similarity index 100% rename from tests/letstest/scripts/bootstrap_os_packages.sh rename to letstest/scripts/bootstrap_os_packages.sh diff --git a/tests/letstest/scripts/test_apache2.sh b/letstest/scripts/test_apache2.sh similarity index 96% rename from tests/letstest/scripts/test_apache2.sh rename to letstest/scripts/test_apache2.sh index 77dc35f1e..9d9ca6c12 100755 --- a/tests/letstest/scripts/test_apache2.sh +++ b/letstest/scripts/test_apache2.sh @@ -59,7 +59,7 @@ fi cd letsencrypt echo "Bootstrapping dependencies..." -sudo tests/letstest/scripts/bootstrap_os_packages.sh +sudo letstest/scripts/bootstrap_os_packages.sh if [ $? -ne 0 ] ; then exit 1 fi @@ -113,7 +113,7 @@ elif [ "$OS_TYPE" = "centos" ]; then fi OPENSSL_VERSION=$(strings "$MOD_SSL_LOCATION" | egrep -o -m1 '^OpenSSL ([0-9]\.[^ ]+) ' | tail -c +9) APACHE_VERSION=$(sudo $APACHE_NAME -v | egrep -o 'Apache/([0-9]\.[^ ]+)' | tail -c +8) -"venv/bin/python" tests/letstest/scripts/test_openssl_version.py "$OPENSSL_VERSION" "$APACHE_VERSION" +"venv/bin/python" letstest/scripts/test_openssl_version.py "$OPENSSL_VERSION" "$APACHE_VERSION" if [ $? -ne 0 ] ; then FAIL=1 fi diff --git a/tests/letstest/scripts/test_openssl_version.py b/letstest/scripts/test_openssl_version.py similarity index 100% rename from tests/letstest/scripts/test_openssl_version.py rename to letstest/scripts/test_openssl_version.py diff --git a/tests/letstest/scripts/test_sdists.sh b/letstest/scripts/test_sdists.sh similarity index 92% rename from tests/letstest/scripts/test_sdists.sh rename to letstest/scripts/test_sdists.sh index b0d53fb67..562169524 100755 --- a/tests/letstest/scripts/test_sdists.sh +++ b/letstest/scripts/test_sdists.sh @@ -2,7 +2,7 @@ cd letsencrypt -BOOTSTRAP_SCRIPT="tests/letstest/scripts/bootstrap_os_packages.sh" +BOOTSTRAP_SCRIPT="letstest/scripts/bootstrap_os_packages.sh" VENV_PATH=venv # install OS packages @@ -41,7 +41,7 @@ for pkg_dir in acme certbot $PLUGINS; do cd - done -VERSION=$(python tests/letstest/scripts/version.py) +VERSION=$(python letstest/scripts/version.py) # test sdists cd $TEMP_DIR for pkg in acme certbot $PLUGINS; do diff --git a/tests/letstest/scripts/version.py b/letstest/scripts/version.py similarity index 85% rename from tests/letstest/scripts/version.py rename to letstest/scripts/version.py index dce2eaec2..6e538b032 100755 --- a/tests/letstest/scripts/version.py +++ b/letstest/scripts/version.py @@ -9,10 +9,10 @@ from os.path import abspath, dirname, join import re -def certbot_version(caller_dir): +def certbot_version(letstest_scripts_dir): """Return the version number stamped in certbot/__init__.py.""" return re.search('''^__version__ = ['"](.+)['"].*''', - file_contents(join(dirname(dirname(dirname(caller_dir))), + file_contents(join(dirname(dirname(letstest_scripts_dir)), 'certbot', 'certbot', '__init__.py')), diff --git a/letstest/setup.py b/letstest/setup.py new file mode 100644 index 000000000..a552cf920 --- /dev/null +++ b/letstest/setup.py @@ -0,0 +1,45 @@ +from setuptools import find_packages +from setuptools import setup + +setup( + name='letstest', + version='1.0', + description='Test Certbot on different AWS images', + url='https://github.com/certbot/certbot', + author='Certbot Project', + author_email='certbot-dev@eff.org', + license='Apache License 2.0', + python_requires='>=3.6', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Security', + ], + + packages=find_packages(), + include_package_data=True, + install_requires=[ + # awscli isn't required by the tests themselves, but it is a useful + # tool to have when using these tests to generate keys and control + # running instances so the dependency is declared here for convenience. + 'awscli', + 'boto3', + 'botocore', + # The API from Fabric 2.0+ is used instead of the 1.0 API. + 'fabric>=2', + 'pyyaml', + ], + entry_points={ + 'console_scripts': [ + 'letstest=letstest.multitester:main', + ], + } +) diff --git a/tests/letstest/apache2_targets.yaml b/letstest/targets/apache2_targets.yaml similarity index 100% rename from tests/letstest/apache2_targets.yaml rename to letstest/targets/apache2_targets.yaml diff --git a/tests/letstest/targets.yaml b/letstest/targets/targets.yaml similarity index 100% rename from tests/letstest/targets.yaml rename to letstest/targets/targets.yaml diff --git a/tests/letstest/auto_targets.yaml b/tests/letstest/auto_targets.yaml deleted file mode 100644 index 01d410227..000000000 --- a/tests/letstest/auto_targets.yaml +++ /dev/null @@ -1,59 +0,0 @@ -# These images are located in us-east-1. - -targets: - #----------------------------------------------------------------------------- - #Ubuntu - - ami: ami-095192256fe1477ad - name: ubuntu18.04LTS - type: ubuntu - virt: hvm - user: ubuntu - - ami: ami-09677e0a6b14905b0 - name: ubuntu16.04LTS - type: ubuntu - virt: hvm - user: ubuntu - #----------------------------------------------------------------------------- - # Debian - - ami: ami-01db78123b2b99496 - name: debian10 - type: ubuntu - virt: hvm - user: admin - - ami: ami-003f19e0e687de1cd - name: debian9 - type: ubuntu - virt: hvm - user: admin - - ami: ami-0ed54dd1b25657636 - name: debian9_arm64 - type: ubuntu - virt: hvm - user: admin - machine_type: a1.medium - #----------------------------------------------------------------------------- - # Other Redhat Distros - - ami: ami-0916c408cb02e310b - name: RHEL7 - type: centos - virt: hvm - user: ec2-user - - ami: ami-0c322300a1dd5dc79 - name: RHEL8 - type: centos - virt: hvm - user: ec2-user - #----------------------------------------------------------------------------- - # CentOS - # These Marketplace AMIs must, irritatingly, have their terms manually - # agreed to on the AWS marketplace site for any new AWS account using them... - - ami: ami-9887c6e7 - name: centos7 - type: centos - virt: hvm - user: centos - - ami: ami-01ca03df4a6012157 - name: centos8 - type: centos - virt: hvm - user: centos diff --git a/tests/letstest/requirements.txt b/tests/letstest/requirements.txt deleted file mode 100644 index b49489283..000000000 --- a/tests/letstest/requirements.txt +++ /dev/null @@ -1,22 +0,0 @@ -awscli==1.19.36 -bcrypt==3.2.0 -boto3==1.17.36 -botocore==1.20.36 -cffi==1.14.5 -colorama==0.4.3 -cryptography==3.4.6 -docutils==0.15.2 -fabric==2.6.0 -invoke==1.5.0 -jmespath==0.10.0 -paramiko==2.7.2 -pathlib2==2.3.5 -pyasn1==0.4.8 -pycparser==2.20 -PyNaCl==1.4.0 -python-dateutil==2.8.1 -PyYAML==5.4.1 -rsa==4.5 -s3transfer==0.3.6 -six==1.15.0 -urllib3==1.26.4 diff --git a/tools/_release.sh b/tools/_release.sh index ba54536bf..4e118c2d7 100755 --- a/tools/_release.sh +++ b/tools/_release.sh @@ -211,8 +211,8 @@ git add certbot/CHANGELOG.md git commit -m "Add contents to certbot/CHANGELOG.md for next version" echo "New root: $root" -echo "Test commands (in the letstest repo):" -echo 'python multitester.py --saveinstances targets.yaml $AWS_KEY $USERNAME scripts/test_apache2.sh' +echo "Test commands (in the letstest directory):" +echo 'letstest --saveinstances targets/targets.yaml $AWS_KEY $USERNAME scripts/test_apache2.sh' echo "In order to upload packages run the following command:" echo twine upload "$root/dist.$version/*/*" diff --git a/tools/pinning/pyproject.toml b/tools/pinning/pyproject.toml index 34fea18a6..50611e7da 100644 --- a/tools/pinning/pyproject.toml +++ b/tools/pinning/pyproject.toml @@ -32,9 +32,18 @@ certbot-nginx = {path = "../../certbot-nginx", extras = ["docs"]} certbot-apache = {path = "../../certbot-apache", extras = ["dev"]} certbot = {path = "../../certbot", extras = ["dev", "docs"]} acme = {path = "../../acme", extras = ["dev", "docs"]} +letstest = {path = "../../letstest"} windows-installer = {path = "../../windows-installer"} # Extra dependencies +# awscli is just listed here as a performance optimization. As of writing this, +# there are some conflicts in shared dependencies between it and other packages +# we depend on. To try and resolve them, poetry searches through older versions +# of awscli to see if that resolves the conflict, but there are over 1000 +# versions of awscli on PyPI so this process takes too long. Providing a high +# minimum version here prevents poetry from searching this path and it fairly +# quickly resolves the dependency conflict in another way. +awscli = ">=1.19.62" # As of writing this, cython is a build dependency of pyyaml. Since there # doesn't appear to be a good way to automatically track down and pin build # dependencies in Python (see diff --git a/tools/requirements.txt b/tools/requirements.txt index b662744c6..4fb1f87e6 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -12,25 +12,26 @@ appdirs==1.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or pyt appnope==0.1.2 astroid==2.3.3; python_version >= "3.6" attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +awscli==1.19.62; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.6.0") azure-devops==6.0.0b4; python_version >= "3.6" -babel==2.9.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" +babel==2.9.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" backcall==0.2.0 -bcrypt==3.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +bcrypt==3.2.0; python_version >= "3.6" beautifulsoup4==4.9.3; python_version >= "3.6" and python_version < "4.0" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -boto3==1.17.53; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -botocore==1.20.53; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +boto3==1.17.62; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +botocore==1.20.62; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" cachecontrol==0.12.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" cached-property==1.5.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -cachetools==4.2.1; python_version >= "3.5" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") +cachetools==4.2.2; python_version >= "3.5" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") cachy==0.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" certifi==2020.12.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -cffi==1.14.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +cffi==1.14.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" chardet==4.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" cleo==0.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" clikit==0.6.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" cloudflare==2.8.15; python_version >= "3.6" -colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") +colorama==0.4.3; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") configargparse==1.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" configobj==5.0.6; python_version >= "3.6" coverage==4.5.4; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0" and python_version < "4") @@ -47,14 +48,15 @@ docker-compose==1.26.2; python_version >= "3.6" and python_full_version < "3.0.0 docker==4.2.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" dockerpty==0.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" docopt==0.6.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -docutils==0.16; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") +docutils==0.15.2; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") execnet==1.8.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +fabric==2.6.0; python_version >= "3.6" filelock==3.0.12; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "4.0" future==0.18.2; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.3.0" google-api-core==1.26.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -google-api-python-client==2.2.0; python_version >= "3.6" +google-api-python-client==2.3.0; python_version >= "3.6" google-auth-httplib2==0.1.0; python_version >= "3.6" -google-auth==1.29.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +google-auth==1.30.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" googleapis-common-protos==1.53.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" html5lib==1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" httplib2==0.19.1; python_version >= "3.6" @@ -62,6 +64,7 @@ idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python imagesize==1.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" importlib-metadata==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "3.8" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") importlib-resources==5.1.2; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "3.7" +invoke==1.5.0; python_version >= "3.6" ipdb==0.13.7; python_version >= "3.6" ipython-genutils==0.2.0; python_version == "3.6" ipython==7.16.1; python_version == "3.6" @@ -93,6 +96,7 @@ paramiko==2.7.2; python_version >= "3.6" and python_full_version < "3.0.0" or py parsedatetime==2.6; python_version >= "3.6" parso==0.8.2; python_version == "3.6" pastel==0.2.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" +pathlib2==2.3.5; python_version >= "3.6" pexpect==4.8.0 pickleshare==0.7.5 pkginfo==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" @@ -105,14 +109,14 @@ protobuf==3.15.8; python_version >= "3.6" and python_full_version < "3.0.0" or p ptyprocess==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -pyasn1==0.4.8; python_version >= "3.6" and python_version < "4" +pyasn1==0.4.8; python_version >= "3.6" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") pycparser==2.20; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -pygithub==1.54.1; python_version >= "3.6" +pygithub==1.55; python_version >= "3.6" pygments==2.8.1 -pyjwt==1.7.1; python_version >= "3.6" +pyjwt==2.1.0; python_version >= "3.6" pylev==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" pylint==2.4.3; python_version >= "3.5" -pynacl==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +pynacl==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" pynsist==2.7; python_version >= "3.6" pyopenssl==20.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" @@ -126,7 +130,7 @@ pytest==3.2.5 python-augeas==0.5.0 python-dateutil==2.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" python-digitalocean==1.16.0; python_version >= "3.6" -python-dotenv==0.17.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +python-dotenv==0.17.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" pytz==2021.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.6.0" pywin32-ctypes==0.2.0; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "win32" pywin32==300; sys_platform == "win32" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") @@ -140,10 +144,10 @@ requests-toolbelt==0.9.1; python_version >= "3.6" and python_full_version < "3.0 requests==2.25.1; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_full_version >= "3.6.0" and python_version < "4.0" rfc3986==1.4.0; python_version >= "3.6" rsa==4.7.2; python_version >= "3.6" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") -s3transfer==0.3.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +s3transfer==0.4.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" secretstorage==3.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" shellingham==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -six==1.15.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +six==1.15.0; python_version == "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version == "3.6" snowballstemmer==2.1.0; python_version >= "3.6" soupsieve==2.2.1; python_version >= "3.6" sphinx-rtd-theme==0.5.2; python_version >= "3.6" @@ -166,7 +170,7 @@ typed-ast==1.4.3; implementation_name == "cpython" and python_version < "3.8" an typing-extensions==3.7.4.3; python_version >= "3.6" uritemplate==3.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6" -virtualenv==20.4.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" +virtualenv==20.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" wcwidth==0.2.5; python_version == "3.6" webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" diff --git a/tools/venv.py b/tools/venv.py index 2e0607e70..f3f5781fa 100755 --- a/tools/venv.py +++ b/tools/venv.py @@ -44,6 +44,7 @@ REQUIREMENTS = [ '-e certbot-nginx', '-e certbot-compatibility-test', '-e certbot-ci', + '-e letstest', ] if sys.platform == 'win32': diff --git a/tox.ini b/tox.ini index f7db07b52..a45766d87 100644 --- a/tox.ini +++ b/tox.ini @@ -277,22 +277,26 @@ passenv = DOCKER_* setenv = {[testenv:oldest]setenv} [testenv:test-farm-tests-base] -changedir = tests/letstest -deps = -rtests/letstest/requirements.txt +changedir = letstest +# The package to install is in the current working directory because of the +# value of changedir. +commands = {[base]pip_install} . passenv = AWS_* setenv = AWS_DEFAULT_REGION=us-east-1 [testenv:test-farm-apache2] changedir = {[testenv:test-farm-tests-base]changedir} -commands = {toxinidir}/tools/retry.sh python multitester.py apache2_targets.yaml {env:AWS_EC2_PEM_FILE} SET_BY_ENV scripts/test_apache2.sh --repo {toxinidir} -deps = {[testenv:test-farm-tests-base]deps} +commands = + {[testenv:test-farm-tests-base]commands} + {toxinidir}/tools/retry.sh letstest targets/apache2_targets.yaml {env:AWS_EC2_PEM_FILE} SET_BY_ENV scripts/test_apache2.sh --repo {toxinidir} passenv = {[testenv:test-farm-tests-base]passenv} setenv = {[testenv:test-farm-tests-base]setenv} [testenv:test-farm-sdists] changedir = {[testenv:test-farm-tests-base]changedir} -commands = {toxinidir}/tools/retry.sh python multitester.py targets.yaml {env:AWS_EC2_PEM_FILE} SET_BY_ENV scripts/test_sdists.sh --repo {toxinidir} -deps = {[testenv:test-farm-tests-base]deps} +commands = + {[testenv:test-farm-tests-base]commands} + {toxinidir}/tools/retry.sh letstest targets/targets.yaml {env:AWS_EC2_PEM_FILE} SET_BY_ENV scripts/test_sdists.sh --repo {toxinidir} passenv = {[testenv:test-farm-tests-base]passenv} setenv = {[testenv:test-farm-tests-base]setenv} From bb6a076fda04fb26458b9e856878edfba292307a Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 4 May 2021 11:48:09 -0700 Subject: [PATCH 08/16] Update changelog for 1.15.0 release --- certbot/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 7648d0ec3..46d9117d7 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,7 +2,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). -## 1.15.0 - master +## 1.15.0 - 2021-05-04 ### Added From 67e3c5474447a20fb8a574be8745c4b2dac0d480 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 4 May 2021 11:50:10 -0700 Subject: [PATCH 09/16] Release 1.15.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/certbot/__init__.py | 2 +- certbot/docs/cli-help.txt | 16 +++++++--------- 20 files changed, 26 insertions(+), 28 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index 2e2eb6a6d..e414442de 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index efc9ea38a..9902bfdfb 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 51d555fbb..82094458f 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index b9c0244fb..6c6aa9cbd 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index b3185a32d..1f7927a3b 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index 656800f72..f158a5c85 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 09713b928..3813cb7a2 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 18bff0761..65b06b420 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 8d8656fdc..13b179acb 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index b7e984f2b..7ce24c65d 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index 372e2d5dd..ddc1843f3 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index 5136ed274..b49a47813 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index e9e1a53b0..a5b81c9af 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index c6c27bdd6..02e0cec90 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 39315c866..15f75e4df 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index afff18efa..6c4642955 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index bbd85944f..775dd6dce 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index 740218449..fd01f09dd 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.15.0.dev0' +version = '1.15.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index fbf8160fc..0cdbd46a5 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,3 +1,3 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '1.15.0.dev0' +__version__ = '1.15.0' diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt index c5490c100..5d772d90e 100644 --- a/certbot/docs/cli-help.txt +++ b/certbot/docs/cli-help.txt @@ -118,12 +118,12 @@ 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/1.14.0 - (certbot(-auto); OS_NAME OS_VERSION) Authenticator/XXX - Installer/YYY (SUBCOMMAND; flags: FLAGS) - Py/major.minor.patchlevel). The flags encoded in the - user agent are: --duplicate, --force-renew, --allow- - subset-of-names, -n, and whether any hooks are set. + "". (default: CertbotACMEClient/1.15.0 (certbot; + OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY + (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel). + The flags encoded in the user agent are: --duplicate, + --force-renew, --allow-subset-of-names, -n, and + whether any hooks are set. --user-agent-comment USER_AGENT_COMMENT Add a comment to the default user agent string. May be used when repackaging Certbot or calling it from @@ -216,9 +216,7 @@ testing: (invalid) certificates; equivalent to --server https://acme-staging-v02.api.letsencrypt.org/directory (default: False) - --debug Show tracebacks in case of errors, and allow certbot- - auto execution on experimental platforms (default: - False) + --debug Show tracebacks in case of errors (default: False) --no-verify-ssl Disable verification of the ACME server's certificate. (default: False) --http-01-port HTTP01_PORT From 484309ed954bdca735cac08b2527ae98530abe42 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 4 May 2021 11:50:12 -0700 Subject: [PATCH 10/16] Add contents to certbot/CHANGELOG.md for next version --- certbot/CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md index 46d9117d7..fd2f0ffb4 100644 --- a/certbot/CHANGELOG.md +++ b/certbot/CHANGELOG.md @@ -2,6 +2,22 @@ Certbot adheres to [Semantic Versioning](https://semver.org/). +## 1.16.0 - master + +### Added + +* + +### Changed + +* + +### Fixed + +* + +More details about these changes can be found on our GitHub repo. + ## 1.15.0 - 2021-05-04 ### Added From 56c781aec47ac4b7c30f64a6be46eb34a762561a Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 4 May 2021 11:50:12 -0700 Subject: [PATCH 11/16] Bump version to 1.16.0 --- acme/setup.py | 2 +- certbot-apache/setup.py | 2 +- certbot-compatibility-test/setup.py | 2 +- certbot-dns-cloudflare/setup.py | 2 +- certbot-dns-cloudxns/setup.py | 2 +- certbot-dns-digitalocean/setup.py | 2 +- certbot-dns-dnsimple/setup.py | 2 +- certbot-dns-dnsmadeeasy/setup.py | 2 +- certbot-dns-gehirn/setup.py | 2 +- certbot-dns-google/setup.py | 2 +- certbot-dns-linode/setup.py | 2 +- certbot-dns-luadns/setup.py | 2 +- certbot-dns-nsone/setup.py | 2 +- certbot-dns-ovh/setup.py | 2 +- certbot-dns-rfc2136/setup.py | 2 +- certbot-dns-route53/setup.py | 2 +- certbot-dns-sakuracloud/setup.py | 2 +- certbot-nginx/setup.py | 2 +- certbot/certbot/__init__.py | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/acme/setup.py b/acme/setup.py index e414442de..6fa49dafc 100644 --- a/acme/setup.py +++ b/acme/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py index 9902bfdfb..898e4e3e7 100644 --- a/certbot-apache/setup.py +++ b/certbot-apache/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py index 82094458f..9567bbef6 100644 --- a/certbot-compatibility-test/setup.py +++ b/certbot-compatibility-test/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' install_requires = [ 'certbot', diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py index 6c6aa9cbd..3e3a3d1ba 100644 --- a/certbot-dns-cloudflare/setup.py +++ b/certbot-dns-cloudflare/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-cloudxns/setup.py b/certbot-dns-cloudxns/setup.py index 1f7927a3b..20b499327 100644 --- a/certbot-dns-cloudxns/setup.py +++ b/certbot-dns-cloudxns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py index f158a5c85..fba2fbc5f 100644 --- a/certbot-dns-digitalocean/setup.py +++ b/certbot-dns-digitalocean/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py index 3813cb7a2..c0da63d71 100644 --- a/certbot-dns-dnsimple/setup.py +++ b/certbot-dns-dnsimple/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py index 65b06b420..2feae0bd1 100644 --- a/certbot-dns-dnsmadeeasy/setup.py +++ b/certbot-dns-dnsmadeeasy/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py index 13b179acb..d24f6b309 100644 --- a/certbot-dns-gehirn/setup.py +++ b/certbot-dns-gehirn/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py index 7ce24c65d..dd43f4992 100644 --- a/certbot-dns-google/setup.py +++ b/certbot-dns-google/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py index ddc1843f3..72c7ee2fd 100644 --- a/certbot-dns-linode/setup.py +++ b/certbot-dns-linode/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py index b49a47813..b2c54779f 100644 --- a/certbot-dns-luadns/setup.py +++ b/certbot-dns-luadns/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py index a5b81c9af..a78b6c3b7 100644 --- a/certbot-dns-nsone/setup.py +++ b/certbot-dns-nsone/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py index 02e0cec90..4831fa480 100644 --- a/certbot-dns-ovh/setup.py +++ b/certbot-dns-ovh/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py index 15f75e4df..a19753e79 100644 --- a/certbot-dns-rfc2136/setup.py +++ b/certbot-dns-rfc2136/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py index 6c4642955..b1c1d786c 100644 --- a/certbot-dns-route53/setup.py +++ b/certbot-dns-route53/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py index 775dd6dce..7b76bb324 100644 --- a/certbot-dns-sakuracloud/setup.py +++ b/certbot-dns-sakuracloud/setup.py @@ -4,7 +4,7 @@ import sys from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Please update tox.ini when modifying dependency version requirements install_requires = [ diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py index fd01f09dd..f42a6e85d 100644 --- a/certbot-nginx/setup.py +++ b/certbot-nginx/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages from setuptools import setup -version = '1.15.0' +version = '1.16.0.dev0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py index 0cdbd46a5..4557ee399 100644 --- a/certbot/certbot/__init__.py +++ b/certbot/certbot/__init__.py @@ -1,3 +1,3 @@ """Certbot client.""" # version number like 1.2.3a0, must have at least 2 parts, like 1.2 -__version__ = '1.15.0' +__version__ = '1.16.0.dev0' From 934de48d44e431b01dcf750de88d24ca740119d5 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Wed, 5 May 2021 15:49:06 -0700 Subject: [PATCH 12/16] fix typo (#8828) --- certbot-ci/snap_integration_tests/dns_tests/test_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certbot-ci/snap_integration_tests/dns_tests/test_main.py b/certbot-ci/snap_integration_tests/dns_tests/test_main.py index 721352c04..d008efc67 100644 --- a/certbot-ci/snap_integration_tests/dns_tests/test_main.py +++ b/certbot-ci/snap_integration_tests/dns_tests/test_main.py @@ -44,4 +44,4 @@ def test_dns_plugin_install(dns_snap_path): 'certbot:certbot-metadata']) subprocess.check_call(['snap', 'install', '--dangerous', dns_snap_path]) finally: - subprocess.call(['snap', 'remove', 'plugin_name']) + subprocess.call(['snap', 'remove', plugin_name]) From 7eae058af595f526b42031c646b1febebdcffeca Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 7 May 2021 13:10:02 -0700 Subject: [PATCH 13/16] Remove OS instructions (#8833) Fixes https://github.com/certbot/certbot/issues/8832. [These instructions are creating confusion among users](https://github.com/certbot/certbot/issues/8832) and [frustration among packagers](https://pagure.io/fesco/issue/2570) for whom the warning at the top of the OS packaging section doesn't apply. Because of this, I think we should remove them in favor of our instruction generator and snap/docker/pip instructions. I also told Fedora packagers that we could probably do this in response to them continuing to improve their Certbot packages which they've done through things like the renewal timer that is now enabled by default. --- certbot/docs/install.rst | 111 --------------------------------------- 1 file changed, 111 deletions(-) diff --git a/certbot/docs/install.rst b/certbot/docs/install.rst index 99cf11c16..4533cfcc1 100644 --- a/certbot/docs/install.rst +++ b/certbot/docs/install.rst @@ -125,117 +125,6 @@ of the ``/etc/letsencrypt`` directory, see :ref:`where-certs`. .. _Docker: https://docker.com .. _`install Docker`: https://docs.docker.com/engine/installation/ -Operating System Packages -------------------------- - -.. warning:: While the Certbot team tries to keep the Certbot packages offered - by various operating systems working in the most basic sense, due to - distribution policies and/or the limited resources of distribution - maintainers, Certbot OS packages often have problems that other distribution - mechanisms do not. The packages are often old resulting in a lack of bug - fixes and features and a worse TLS configuration than is generated by newer - versions of Certbot. They also may not configure certificate renewal for you - or have all of Certbot's plugins available. For reasons like these, we - recommend most users follow the instructions at - https://certbot.eff.org/instructions and OS packages are only documented - here as an alternative. - -**Arch Linux** - -.. code-block:: shell - - sudo pacman -S certbot - -**Debian** - -If you run Debian Buster or Debian testing/Sid, you can easily install certbot -packages through commands like: - -.. code-block:: shell - - sudo apt-get update - sudo apt-get install certbot - -If you run Debian Stretch, we recommend you use the packages in Debian -backports repository. First you'll have to follow the instructions at -https://backports.debian.org/Instructions/ to enable the Stretch backports repo, -if you have not already done so. Then run: - -.. code-block:: shell - - sudo apt-get install certbot -t stretch-backports - -In all of these cases, there also packages available to help Certbot integrate -with Apache, nginx, or various DNS services. If you are using Apache or nginx, -we strongly recommend that you install the ``python-certbot-apache`` or -``python-certbot-nginx`` package so that Certbot can fully automate HTTPS -configuration for your server. A full list of these packages can be found -through a command like: - -.. code-block:: shell - - apt search 'python-certbot*' - -They can be installed by running the same installation command above but -replacing ``certbot`` with the name of the desired package. - -**Ubuntu** - -If you run Ubuntu, certbot can be installed using: - -.. code-block:: shell - - sudo apt-get install certbot - -Optionally to install the Certbot Apache plugin, you can use: - -.. code-block:: shell - - sudo apt-get install python3-certbot-apache - -**Fedora** - -.. code-block:: shell - - sudo dnf install certbot python3-certbot-apache - -**FreeBSD** - - * Port: ``cd /usr/ports/security/py-certbot && make install clean`` - * Package: ``pkg install py37-certbot`` - -**Gentoo** - -The official Certbot client is available in Gentoo Portage. From the -official Certbot plugins, three of them are also available in Portage. -They need to be installed separately if you require their functionality. - -.. code-block:: shell - - emerge -av app-crypt/certbot - emerge -av app-crypt/certbot-apache - emerge -av app-crypt/certbot-nginx - emerge -av app-crypt/certbot-dns-nsone - -.. Note:: The ``app-crypt/certbot-dns-nsone`` package has a different - maintainer than the other packages and can lag behind in version. - -**NetBSD** - - * Build from source: ``cd /usr/pkgsrc/security/py-certbot && make install clean`` - * Install pre-compiled package: ``pkg_add py37-certbot`` - -**OpenBSD** - - * Port: ``cd /usr/ports/security/letsencrypt/client && make install clean`` - * Package: ``pkg_add letsencrypt`` - -**Other Operating Systems** - -OS packaging is an ongoing effort. If you'd like to package -Certbot for your distribution of choice please have a -look at the :doc:`packaging`. - .. _certbot-auto: Certbot-Auto From b0552e1939a8a120bf65a1c7caaaebc45b10f040 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Mon, 10 May 2021 21:11:31 +0200 Subject: [PATCH 14/16] Fix Sphinx builds (#8838) Since Saturday the CI pipeline is failing due to several Sphinx errors. See https://dev.azure.com/certbot/certbot/_build/results?buildId=3928&view=logs&j=d74e04fe-9740-597d-e9fa-1d0400037dfd&t=dde413a4-f24c-59a0-9684-e33d79f9aa02 First, the build of certbot-dns-google is failing because of a particular configuration. It seems that this configuration has been written here to activate the support of the RST instruction `.. code-block:: json` in documentation. However, it does not seem to be necessary for a similar situation in certbot-dns-route53 documentation. So let's try to remove it and fix the Sphinx builds. Second, Sphinx builds were not pinning dependencies, so Sphinx 4.x (that has been released yesterday) started to be used in the pipeline. Sadly this new version is not compatible with the plugin `repoze.sphinx.autointerface`, used to extract documentation from `zope.interface`. So I fixed the pinning and also explicitly pin Sphinx to 3.5.x for now. Technically speaking the second action is sufficient to fix the first error, but I keep the dedicated solution because it improves the documentation in my opinion. This situation could be fixed by not requiring `repoze.sphinx.autointerface`, but this is possible only if we remove `zope.interface` from Certbot. Luckily I started the work few days ago ;). * Remove explicit lexer call in certbot-dns-google doc builds. * Write a valid JSON file in the documentation * Apply constraints to sphinx build environments * Pin Sphinx to 3.5.4 * Update dependencies * Pin traitlets --- .../templates/steps/sphinx-steps.yml | 2 +- .../certbot_dns_google/__init__.py | 12 +++++-- certbot-dns-google/docs/_ext/jsonlexer.py | 16 ---------- certbot-dns-google/docs/conf.py | 3 +- tools/pinning/pyproject.toml | 11 +++++++ tools/requirements.txt | 32 +++++++++---------- 6 files changed, 39 insertions(+), 37 deletions(-) delete mode 100644 certbot-dns-google/docs/_ext/jsonlexer.py diff --git a/.azure-pipelines/templates/steps/sphinx-steps.yml b/.azure-pipelines/templates/steps/sphinx-steps.yml index 23c258bbc..afc273f8f 100644 --- a/.azure-pipelines/templates/steps/sphinx-steps.yml +++ b/.azure-pipelines/templates/steps/sphinx-steps.yml @@ -9,7 +9,7 @@ steps: do echo "" echo "##[group]Building $doc_path" - pip install -q -e $doc_path/..[docs] + pip install -q -e $doc_path/..[docs] -c tools/requirements.txt if ! sphinx-build -W --keep-going -b html $doc_path $doc_path/_build/html; then FINAL_STATUS=1 FAILED_BUILDS[${#FAILED_BUILDS[@]}]="${doc_path%/docs}" diff --git a/certbot-dns-google/certbot_dns_google/__init__.py b/certbot-dns-google/certbot_dns_google/__init__.py index 2d448c590..67ed34a45 100644 --- a/certbot-dns-google/certbot_dns_google/__init__.py +++ b/certbot-dns-google/certbot_dns_google/__init__.py @@ -51,8 +51,16 @@ are automatically obtained by certbot through the `metadata service :caption: Example credentials file: { - "type": "service_account", - ... + "type": "service_account", + "project_id": "...", + "private_key_id": "...", + "private_key": "...", + "client_email": "...", + "client_id": "...", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "..." } The path to this file can be provided interactively or using the diff --git a/certbot-dns-google/docs/_ext/jsonlexer.py b/certbot-dns-google/docs/_ext/jsonlexer.py deleted file mode 100644 index 1ad004d2b..000000000 --- a/certbot-dns-google/docs/_ext/jsonlexer.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Copied from https://stackoverflow.com/a/16863232""" - -def setup(app): - # enable Pygments json lexer - try: - import pygments - if pygments.__version__ >= '1.5': - # use JSON lexer included in recent versions of Pygments - from pygments.lexers import JsonLexer - else: - # use JSON lexer from pygments-json if installed - from pygson.json_lexer import JSONLexer as JsonLexer - except ImportError: - pass # not fatal if we have old (or no) Pygments and no pygments-json - else: - app.add_lexer('json', JsonLexer()) diff --git a/certbot-dns-google/docs/conf.py b/certbot-dns-google/docs/conf.py index 06bb99f46..f4c1f661e 100644 --- a/certbot-dns-google/docs/conf.py +++ b/certbot-dns-google/docs/conf.py @@ -35,8 +35,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', - 'sphinx.ext.viewcode', - 'jsonlexer'] + 'sphinx.ext.viewcode'] autodoc_member_order = 'bysource' autodoc_default_flags = ['show-inheritance'] diff --git a/tools/pinning/pyproject.toml b/tools/pinning/pyproject.toml index 50611e7da..0ff11ac2f 100644 --- a/tools/pinning/pyproject.toml +++ b/tools/pinning/pyproject.toml @@ -70,6 +70,17 @@ pytest-forked = "0.2" # library for now because it causes Certbot tests on Windows to fail. See # https://github.com/certbot/certbot/issues/8732. python-augeas = "0.5.0" +# Because some parts of Certbot documentation are generated from zope.interfaces, +# we need the Sphinx plugin repoze.sphinx.autointerface. But this plugin is not +# maintained anymore, and it is not compatible with Sphinx 4.x. So we need to +# pin Sphinx to 3.5 to make it work. This situation will be unblocked by the +# removal of zope.interface in Certbot. +sphinx = "<4" +# Library traitlets is a transitive dependency of ipdb (traitlets -> ipython -> ipdb). +# Version 5.x is incompatible with Python 3.6 but for some reasons, poetry fails to +# add the appropriate marker and allows this version to be installed under Python 3.6. +# We add a pinning to not create a set of requirements incompatible with Python 3.6. +traitlets = "<5" [tool.poetry.dev-dependencies] diff --git a/tools/requirements.txt b/tools/requirements.txt index 4fb1f87e6..9e442f411 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -11,16 +11,16 @@ apipkg==1.5; python_version >= "3.6" and python_full_version < "3.0.0" or python appdirs==1.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" appnope==0.1.2 astroid==2.3.3; python_version >= "3.6" -attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -awscli==1.19.62; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.6.0") +attrs==21.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +awscli==1.19.69; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.6.0") azure-devops==6.0.0b4; python_version >= "3.6" babel==2.9.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" backcall==0.2.0 bcrypt==3.2.0; python_version >= "3.6" beautifulsoup4==4.9.3; python_version >= "3.6" and python_version < "4.0" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -boto3==1.17.62; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -botocore==1.20.62; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +boto3==1.17.69; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +botocore==1.20.69; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" cachecontrol==0.12.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" cached-property==1.5.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" cachetools==4.2.2; python_version >= "3.5" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") @@ -42,7 +42,7 @@ decorator==5.0.7 deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" distlib==0.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" distro==1.5.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -dns-lexicon==3.5.6; python_version >= "3.6" and python_version < "4.0" +dns-lexicon==3.6.0; python_version >= "3.6" and python_version < "4.0" dnspython==2.1.0; python_version >= "3.6" docker-compose==1.26.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" docker==4.2.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" @@ -52,7 +52,6 @@ docutils==0.15.2; (python_version >= "2.6" and python_full_version < "3.0.0") or execnet==1.8.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" fabric==2.6.0; python_version >= "3.6" filelock==3.0.12; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "4.0" -future==0.18.2; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.3.0" google-api-core==1.26.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" google-api-python-client==2.3.0; python_version >= "3.6" google-auth-httplib2==0.1.0; python_version >= "3.6" @@ -68,7 +67,7 @@ invoke==1.5.0; python_version >= "3.6" ipdb==0.13.7; python_version >= "3.6" ipython-genutils==0.2.0; python_version == "3.6" ipython==7.16.1; python_version == "3.6" -ipython==7.22.0; python_version >= "3.7" +ipython==7.23.1; python_version >= "3.7" isodate==0.6.0; python_version >= "3.6" isort==4.3.21; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" jedi==0.18.0 @@ -83,6 +82,7 @@ keyring==21.8.0; python_version >= "3.6" and python_version < "4.0" and (python_ lazy-object-proxy==1.4.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" lockfile==0.12.2 markupsafe==1.1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" +matplotlib-inline==0.1.2; python_version >= "3.7" mccabe==0.6.1; python_version >= "3.6" mock==4.0.3; python_version >= "3.6" msgpack==1.0.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" @@ -105,14 +105,14 @@ ply==3.11; python_version >= "3.6" poetry-core==1.0.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" poetry==1.1.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" prompt-toolkit==3.0.3 -protobuf==3.15.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +protobuf==3.16.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" ptyprocess==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" pyasn1==0.4.8; python_version >= "3.6" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") pycparser==2.20; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" pygithub==1.55; python_version >= "3.6" -pygments==2.8.1 +pygments==2.9.0 pyjwt==2.1.0; python_version >= "3.6" pylev==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" pylint==2.4.3; python_version >= "3.5" @@ -142,16 +142,16 @@ requests-file==1.5.1; python_version >= "3.6" and python_version < "4.0" requests-oauthlib==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" requests-toolbelt==0.9.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" requests==2.25.1; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_full_version >= "3.6.0" and python_version < "4.0" -rfc3986==1.4.0; python_version >= "3.6" +rfc3986==1.5.0; python_version >= "3.6" rsa==4.7.2; python_version >= "3.6" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") s3transfer==0.4.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" secretstorage==3.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" shellingham==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -six==1.15.0; python_version == "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version == "3.6" +six==1.16.0; python_version == "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version == "3.6" snowballstemmer==2.1.0; python_version >= "3.6" soupsieve==2.2.1; python_version >= "3.6" sphinx-rtd-theme==0.5.2; python_version >= "3.6" -sphinx==3.5.4; python_version >= "3.6" +sphinx==3.5.4; python_version >= "3.5" sphinxcontrib-applehelp==1.0.2; python_version >= "3.6" sphinxcontrib-devhelp==1.0.2; python_version >= "3.6" sphinxcontrib-htmlhelp==1.0.3; python_version >= "3.6" @@ -162,18 +162,18 @@ texttable==1.6.3; python_version >= "3.6" and python_full_version < "3.0.0" or p tldextract==3.1.0; python_version >= "3.6" and python_version < "4.0" toml==0.10.2; python_version == "3.6" and python_full_version < "3.0.0" or python_version > "3.6" and python_full_version < "3.0.0" or python_version == "3.6" and python_full_version >= "3.5.0" or python_version > "3.6" and python_full_version >= "3.5.0" tomlkit==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -tox==3.23.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" +tox==3.23.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" tqdm==4.60.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" traitlets==4.3.3 twine==3.3.0; python_version >= "3.6" typed-ast==1.4.3; implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.6" -typing-extensions==3.7.4.3; python_version >= "3.6" +typing-extensions==3.10.0.0; python_version >= "3.6" uritemplate==3.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6" -virtualenv==20.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" +virtualenv==20.4.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" wcwidth==0.2.5; python_version == "3.6" webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0" -websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +websocket-client==0.59.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" wrapt==1.11.2; python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0") yarg==0.1.9; python_version >= "3.6" zipp==3.4.1; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "3.7" From c788820f5dd9fefd3234c42e658d86b54eb06539 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 10 May 2021 14:32:37 -0700 Subject: [PATCH 15/16] Fix sphinx followup (#8841) I think we should use our `pip_install*` scripts wherever we can and I'm not quite sure yet if I'd call `repoze.sphinx.autointerface` unmaintained. * use pip_install_editable * update sphinx comment --- .azure-pipelines/templates/steps/sphinx-steps.yml | 2 +- tools/pinning/pyproject.toml | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.azure-pipelines/templates/steps/sphinx-steps.yml b/.azure-pipelines/templates/steps/sphinx-steps.yml index afc273f8f..7e1d2ee9d 100644 --- a/.azure-pipelines/templates/steps/sphinx-steps.yml +++ b/.azure-pipelines/templates/steps/sphinx-steps.yml @@ -9,7 +9,7 @@ steps: do echo "" echo "##[group]Building $doc_path" - pip install -q -e $doc_path/..[docs] -c tools/requirements.txt + tools/pip_install_editable.py $doc_path/..[docs] if ! sphinx-build -W --keep-going -b html $doc_path $doc_path/_build/html; then FINAL_STATUS=1 FAILED_BUILDS[${#FAILED_BUILDS[@]}]="${doc_path%/docs}" diff --git a/tools/pinning/pyproject.toml b/tools/pinning/pyproject.toml index 0ff11ac2f..4dee88d51 100644 --- a/tools/pinning/pyproject.toml +++ b/tools/pinning/pyproject.toml @@ -71,10 +71,11 @@ pytest-forked = "0.2" # https://github.com/certbot/certbot/issues/8732. python-augeas = "0.5.0" # Because some parts of Certbot documentation are generated from zope.interfaces, -# we need the Sphinx plugin repoze.sphinx.autointerface. But this plugin is not -# maintained anymore, and it is not compatible with Sphinx 4.x. So we need to -# pin Sphinx to 3.5 to make it work. This situation will be unblocked by the -# removal of zope.interface in Certbot. +# we need the Sphinx plugin repoze.sphinx.autointerface. This plugin is not +# currently compatible with Sphinx>=4 though so we're pinning an older version +# for now. See https://github.com/repoze/repoze.sphinx.autointerface/issues/16 +# for more info. This pinning could also be removed by the removal of +# zope.interface in Certbot. sphinx = "<4" # Library traitlets is a transitive dependency of ipdb (traitlets -> ipython -> ipdb). # Version 5.x is incompatible with Python 3.6 but for some reasons, poetry fails to From c48adc57538f15baf98ef14ea86550015709838c Mon Sep 17 00:00:00 2001 From: alexzorin Date: Tue, 11 May 2021 09:03:35 +1000 Subject: [PATCH 16/16] docker: delete CARGO_HOME (#8839) --- tools/docker/core/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/docker/core/Dockerfile b/tools/docker/core/Dockerfile index 4c614d5e2..14bd3323a 100644 --- a/tools/docker/core/Dockerfile +++ b/tools/docker/core/Dockerfile @@ -39,4 +39,5 @@ RUN apk add --no-cache --virtual .build-deps \ && python tools/pip_install.py --no-cache-dir \ --editable src/acme \ --editable src/certbot \ - && apk del .build-deps + && apk del .build-deps \ + && rm -rf ${HOME}/.cargo