mirror of
https://github.com/certbot/certbot.git
synced 2026-06-04 22:33:00 -04:00
Merge branch 'master' into reduce-default-logging
This commit is contained in:
commit
73dfffeb33
122 changed files with 709 additions and 3205 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ steps:
|
|||
do
|
||||
echo ""
|
||||
echo "##[group]Building $doc_path"
|
||||
pip install -q -e $doc_path/..[docs]
|
||||
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}"
|
||||
|
|
|
|||
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -4,13 +4,11 @@
|
|||
build/
|
||||
dist*/
|
||||
/venv*/
|
||||
/kgs/
|
||||
/.tox/
|
||||
/releases*/
|
||||
/log*
|
||||
letsencrypt.log
|
||||
certbot.log
|
||||
letsencrypt-auto-source/letsencrypt-auto.sig.lzma.base64
|
||||
poetry.lock
|
||||
|
||||
# coverage
|
||||
|
|
@ -32,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'certbot',
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.15.0.dev0'
|
||||
version = '1.16.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -2,7 +2,23 @@
|
|||
|
||||
Certbot adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## 1.15.0 - master
|
||||
## 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.16.0.dev0'
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -94,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)
|
||||
|
||||
@test_util.patch_get_utility()
|
||||
def test_it(self, unused_mock_get_utility):
|
||||
|
|
@ -119,7 +118,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
|
||||
|
|
@ -146,7 +145,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):
|
||||
|
|
@ -157,7 +156,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)
|
||||
|
||||
|
|
@ -175,7 +174,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)
|
||||
|
||||
@test_util.patch_get_utility()
|
||||
def test_without_eab_arguments(self, unused_mock_get_utility):
|
||||
|
|
@ -188,7 +187,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:
|
||||
|
|
@ -213,7 +212,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):
|
||||
|
|
@ -250,7 +249,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()
|
||||
|
|
@ -612,7 +611,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')
|
||||
|
||||
|
|
@ -620,7 +619,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')
|
||||
|
||||
|
|
@ -628,13 +627,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
|
||||
|
|
@ -687,7 +686,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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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__':
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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.info.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.info.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
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -212,20 +212,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")
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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__':
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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__":
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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__':
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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,16 +349,16 @@ class AddDeprecatedArgumentTest(unittest.TestCase):
|
|||
with mock.patch("warnings.warn") 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.assertTrue("--old-option" in mock_warn.call_args[0][0])
|
||||
self.assertIn("is deprecated", mock_warn.call_args[0][0])
|
||||
self.assertIn("--old-option", mock_warn.call_args[0][0])
|
||||
|
||||
def test_warning_with_arg(self):
|
||||
self._call("--old-option", 1)
|
||||
with mock.patch("warnings.warn") 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.assertTrue("--old-option" in mock_warn.call_args[0][0])
|
||||
self.assertIn("is deprecated", mock_warn.call_args[0][0])
|
||||
self.assertIn("--old-option", mock_warn.call_args[0][0])
|
||||
|
||||
def test_help(self):
|
||||
self._call("--old-option", 2)
|
||||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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'
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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])
|
||||
|
|
@ -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:])
|
||||
|
|
@ -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
|
||||
|
|
@ -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())
|
||||
|
|
@ -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
|
||||
|
|
@ -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())
|
||||
|
|
@ -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-----
|
||||
|
|
@ -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 <profile name>
|
||||
[interactive: enter secrets for IAM role]
|
||||
|
|
@ -35,9 +31,9 @@ Note: whatever you pick for `<key name>` 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 <profile name> scripts/<test to run>
|
||||
>letstest targets/targets.yaml /path/to/your/key.pem <profile name> scripts/<test to run>
|
||||
```
|
||||
|
||||
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,15 +48,14 @@ aws ec2 terminate-instances --profile <profile name> --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-<timestamp>` 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
|
||||
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 <pre>test_letsencrypt_auto_*</pre> 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
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue