mirror of
https://github.com/certbot/certbot.git
synced 2026-06-05 06:42:10 -04:00
Merge remote-tracking branch 'upstream/master' into ux_http_plugin_cli_output
This commit is contained in:
commit
d45a2b5dff
135 changed files with 761 additions and 3358 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}"
|
||||
|
|
|
|||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
custom: https://supporters.eff.org/donate/support-work-on-certbot
|
||||
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,12 +4,12 @@ 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.
|
||||
install_requires = [
|
||||
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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.
|
||||
|
|
@ -32,7 +32,7 @@ if os.environ.get('SNAP_BUILD'):
|
|||
# which allows us to potentially upgrade our packages in these distros
|
||||
# as necessary.
|
||||
if os.environ.get('CERTBOT_OLDEST') == '1':
|
||||
install_requires.append('dns-lexicon>=2.2.1')
|
||||
install_requires.append('dns-lexicon>=3.1.0') # Changed parameter name
|
||||
else:
|
||||
install_requires.append('dns-lexicon>=3.2.1')
|
||||
|
||||
|
|
@ -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,12 +4,12 @@ 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.
|
||||
install_requires = [
|
||||
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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,11 +4,11 @@ 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 = [
|
||||
'dns-lexicon>=2.1.22',
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
dns-lexicon==2.2.3
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ 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 = [
|
||||
'dns-lexicon>=2.2.3',
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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,12 +4,12 @@ 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.
|
||||
install_requires = [
|
||||
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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,12 +4,12 @@ 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.
|
||||
install_requires = [
|
||||
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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=[
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
dns-lexicon==2.7.14
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ 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.
|
||||
install_requires = [
|
||||
'dns-lexicon>=2.7.14', # Correct proxy use on OVH provider
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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,11 +4,11 @@ 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 = [
|
||||
'dns-lexicon>=2.1.23',
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
]
|
||||
|
|
@ -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,26 @@
|
|||
|
||||
Certbot adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## 1.15.0 - master
|
||||
## 1.16.0 - master
|
||||
|
||||
### Added
|
||||
|
||||
*
|
||||
|
||||
### Changed
|
||||
|
||||
* DNS plugins based on lexicon now require dns-lexicon >= v3.1.0
|
||||
* Use UTF-8 encoding for renewal configuration files
|
||||
* Windows installer now cleans up old Certbot dependency packages
|
||||
before installing the new ones to avoid version conflicts.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix TypeError due to incompatibility with lexicon >= v3.6.0
|
||||
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -616,7 +616,9 @@ def _delete_if_appropriate(config):
|
|||
|
||||
# don't delete if the archive_dir is used by some other lineage
|
||||
archive_dir = storage.full_archive_path(
|
||||
configobj.ConfigObj(storage.renewal_file_for_certname(config, config.certname)),
|
||||
configobj.ConfigObj(
|
||||
storage.renewal_file_for_certname(config, config.certname),
|
||||
encoding='utf-8', default_encoding='utf-8'),
|
||||
config, config.certname)
|
||||
try:
|
||||
cert_manager.match_and_check_overlaps(config, [lambda x: archive_dir],
|
||||
|
|
@ -1234,12 +1236,8 @@ def renew_cert(config, plugins, lineage):
|
|||
:raises errors.PluginSelectionError: MissingCommandlineFlag if supplied parameters do not pass
|
||||
|
||||
"""
|
||||
try:
|
||||
# installers are used in auth mode to determine domain names
|
||||
installer, auth = plug_sel.choose_configurator_plugins(config, plugins, "certonly")
|
||||
except errors.PluginSelectionError as e:
|
||||
logger.info("Could not choose appropriate plugin: %s", e)
|
||||
raise
|
||||
# installers are used in auth mode to determine domain names
|
||||
installer, auth = plug_sel.choose_configurator_plugins(config, plugins, "certonly")
|
||||
le_client = _init_le_client(config, auth, installer)
|
||||
|
||||
renewed_lineage = _get_and_save_cert(le_client, config, lineage=lineage)
|
||||
|
|
@ -1277,12 +1275,8 @@ def certonly(config, plugins):
|
|||
|
||||
"""
|
||||
# SETUP: Select plugins and construct a client instance
|
||||
try:
|
||||
# installers are used in auth mode to determine domain names
|
||||
installer, auth = plug_sel.choose_configurator_plugins(config, plugins, "certonly")
|
||||
except errors.PluginSelectionError as e:
|
||||
logger.info("Could not choose appropriate plugin: %s", e)
|
||||
raise
|
||||
# installers are used in auth mode to determine domain names
|
||||
installer, auth = plug_sel.choose_configurator_plugins(config, plugins, "certonly")
|
||||
|
||||
le_client = _init_le_client(config, auth, installer)
|
||||
|
||||
|
|
|
|||
|
|
@ -67,13 +67,16 @@ def cert_path_for_cert_name(config: interfaces.IConfig, cert_name: str) -> str:
|
|||
|
||||
"""
|
||||
cert_name_implied_conf = renewal_file_for_certname(config, cert_name)
|
||||
return configobj.ConfigObj(cert_name_implied_conf)["fullchain"]
|
||||
return configobj.ConfigObj(
|
||||
cert_name_implied_conf, encoding='utf-8', default_encoding='utf-8')["fullchain"]
|
||||
|
||||
|
||||
def config_with_defaults(config=None):
|
||||
"""Merge supplied config, if provided, on top of builtin defaults."""
|
||||
defaults_copy = configobj.ConfigObj(constants.RENEWER_DEFAULTS)
|
||||
defaults_copy.merge(config if config is not None else configobj.ConfigObj())
|
||||
defaults_copy = configobj.ConfigObj(
|
||||
constants.RENEWER_DEFAULTS, encoding='utf-8', default_encoding='utf-8')
|
||||
defaults_copy.merge(config if config is not None else configobj.ConfigObj(
|
||||
encoding='utf-8', default_encoding='utf-8'))
|
||||
return defaults_copy
|
||||
|
||||
|
||||
|
|
@ -114,7 +117,7 @@ def write_renewal_config(o_filename, n_filename, archive_dir, target, relevant_d
|
|||
:rtype: configobj.ConfigObj
|
||||
|
||||
"""
|
||||
config = configobj.ConfigObj(o_filename)
|
||||
config = configobj.ConfigObj(o_filename, encoding='utf-8', default_encoding='utf-8')
|
||||
config["version"] = certbot.__version__
|
||||
config["archive_dir"] = archive_dir
|
||||
for kind in ALL_FOUR:
|
||||
|
|
@ -196,7 +199,7 @@ def update_configuration(lineagename, archive_dir, target, cli_config):
|
|||
write_renewal_config(config_filename, temp_filename, archive_dir, target, values)
|
||||
filesystem.replace(temp_filename, config_filename)
|
||||
|
||||
return configobj.ConfigObj(config_filename)
|
||||
return configobj.ConfigObj(config_filename, encoding='utf-8', default_encoding='utf-8')
|
||||
|
||||
|
||||
def get_link_target(link):
|
||||
|
|
@ -324,7 +327,8 @@ def delete_files(config, certname):
|
|||
full_default_archive_dir = full_archive_path(None, config, certname)
|
||||
full_default_live_dir = _full_live_path(config, certname)
|
||||
try:
|
||||
renewal_config = configobj.ConfigObj(renewal_filename)
|
||||
renewal_config = configobj.ConfigObj(
|
||||
renewal_filename, encoding='utf-8', default_encoding='utf-8')
|
||||
except configobj.ConfigObjError:
|
||||
# config is corrupted
|
||||
logger.warning("Could not parse %s. You may wish to manually "
|
||||
|
|
@ -434,7 +438,8 @@ class RenewableCert(interfaces.RenewableCert):
|
|||
# systemwide renewal configuration; self.configfile should be
|
||||
# used to make and save changes.
|
||||
try:
|
||||
self.configfile = configobj.ConfigObj(config_filename)
|
||||
self.configfile = configobj.ConfigObj(
|
||||
config_filename, encoding='utf-8', default_encoding='utf-8')
|
||||
except configobj.ConfigObjError:
|
||||
raise errors.CertStorageError(
|
||||
"error parsing {0}".format(config_filename))
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class LexiconClient:
|
|||
self._find_domain_id(domain)
|
||||
|
||||
try:
|
||||
self.provider.create_record(type='TXT', name=record_name, content=record_content)
|
||||
self.provider.create_record(rtype='TXT', name=record_name, content=record_content)
|
||||
except RequestException as e:
|
||||
logger.debug('Encountered error adding TXT record: %s', e, exc_info=True)
|
||||
raise errors.PluginError('Error adding TXT record: {0}'.format(e))
|
||||
|
|
@ -67,7 +67,7 @@ class LexiconClient:
|
|||
return
|
||||
|
||||
try:
|
||||
self.provider.delete_record(type='TXT', name=record_name, content=record_content)
|
||||
self.provider.delete_record(rtype='TXT', name=record_name, content=record_content)
|
||||
except RequestException as e:
|
||||
logger.debug('Encountered error deleting TXT record: %s', e, exc_info=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class BaseLexiconClientTest:
|
|||
def test_add_txt_record(self: _LexiconAwareTestCase):
|
||||
self.client.add_txt_record(DOMAIN, self.record_name, self.record_content)
|
||||
|
||||
self.provider_mock.create_record.assert_called_with(type='TXT',
|
||||
self.provider_mock.create_record.assert_called_with(rtype='TXT',
|
||||
name=self.record_name,
|
||||
content=self.record_content)
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ class BaseLexiconClientTest:
|
|||
|
||||
self.client.add_txt_record(DOMAIN, self.record_name, self.record_content)
|
||||
|
||||
self.provider_mock.create_record.assert_called_with(type='TXT',
|
||||
self.provider_mock.create_record.assert_called_with(rtype='TXT',
|
||||
name=self.record_name,
|
||||
content=self.record_content)
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ class BaseLexiconClientTest:
|
|||
def test_del_txt_record(self: _LexiconAwareTestCase):
|
||||
self.client.del_txt_record(DOMAIN, self.record_name, self.record_content)
|
||||
|
||||
self.provider_mock.delete_record.assert_called_with(type='TXT',
|
||||
self.provider_mock.delete_record.assert_called_with(rtype='TXT',
|
||||
name=self.record_name,
|
||||
content=self.record_content)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -284,6 +284,8 @@ dns-ispconfig_ Y N DNS Authentication using ISPConfig as DNS server
|
|||
dns-clouddns_ Y N DNS Authentication using CloudDNS API
|
||||
dns-lightsail_ Y N DNS Authentication using Amazon Lightsail DNS API
|
||||
dns-inwx_ Y Y DNS Authentication for INWX through the XML API
|
||||
dns-azure_ Y N DNS Authentication using Azure DNS
|
||||
dns-godaddy_ Y N DNS Authentication using Godaddy DNS
|
||||
================== ==== ==== ===============================================================
|
||||
|
||||
.. _haproxy: https://github.com/greenhost/certbot-haproxy
|
||||
|
|
@ -298,6 +300,8 @@ dns-inwx_ Y Y DNS Authentication for INWX through the XML API
|
|||
.. _dns-clouddns: https://github.com/vshosting/certbot-dns-clouddns
|
||||
.. _dns-lightsail: https://github.com/noi/certbot-dns-lightsail
|
||||
.. _dns-inwx: https://github.com/oGGy990/certbot-dns-inwx/
|
||||
.. _dns-azure: https://github.com/binkhq/certbot-dns-azure
|
||||
.. _dns-godaddy: https://github.com/miigotu/certbot-dns-godaddy
|
||||
|
||||
If you're interested, you can also :ref:`write your own plugin <dev-plugin>`.
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
def test_it(self):
|
||||
with mock.patch("certbot._internal.client.acme_client.BackwardsCompatibleClientV2") as mock_client:
|
||||
|
|
@ -118,7 +117,7 @@ class RegisterTest(test_util.ConfigTestCase):
|
|||
mock_client().new_account_and_tos.side_effect = [mx_err, mock.MagicMock()]
|
||||
self._call()
|
||||
self.assertEqual(mock_get_email.call_count, 1)
|
||||
self.assertTrue(mock_prepare.called)
|
||||
self.assertIs(mock_prepare.called, True)
|
||||
|
||||
def test_email_invalid_noninteractive(self):
|
||||
from acme import messages
|
||||
|
|
@ -145,7 +144,7 @@ class RegisterTest(test_util.ConfigTestCase):
|
|||
self.config.dry_run = False
|
||||
self._call()
|
||||
mock_logger.debug.assert_called_once_with(mock.ANY)
|
||||
self.assertTrue(mock_prepare.called)
|
||||
self.assertIs(mock_prepare.called, True)
|
||||
|
||||
@mock.patch("certbot._internal.client.display_ops.get_email")
|
||||
def test_dry_run_no_staging_account(self, mock_get_email):
|
||||
|
|
@ -156,7 +155,7 @@ class RegisterTest(test_util.ConfigTestCase):
|
|||
self.config.dry_run = True
|
||||
self._call()
|
||||
# check Certbot did not ask the user to provide an email
|
||||
self.assertFalse(mock_get_email.called)
|
||||
self.assertIs(mock_get_email.called, False)
|
||||
# check Certbot created an account with no email. Contact should return empty
|
||||
self.assertFalse(mock_client().new_account_and_tos.call_args[0][0].contact)
|
||||
|
||||
|
|
@ -173,7 +172,7 @@ class RegisterTest(test_util.ConfigTestCase):
|
|||
self.config.eab_hmac_key = "J2OAqW4MHXsrHVa_PVg0Y-L_R4SYw0_aL1le6mfblbE"
|
||||
self._call()
|
||||
|
||||
self.assertTrue(mock_eab_from_data.called)
|
||||
self.assertIs(mock_eab_from_data.called, True)
|
||||
|
||||
def test_without_eab_arguments(self):
|
||||
with mock.patch("certbot._internal.client.acme_client.BackwardsCompatibleClientV2") as mock_client:
|
||||
|
|
@ -185,7 +184,7 @@ class RegisterTest(test_util.ConfigTestCase):
|
|||
self.config.eab_hmac_key = None
|
||||
self._call()
|
||||
|
||||
self.assertFalse(mock_eab_from_data.called)
|
||||
self.assertIs(mock_eab_from_data.called, False)
|
||||
|
||||
def test_external_account_required_without_eab_arguments(self):
|
||||
with mock.patch("certbot._internal.client.acme_client.BackwardsCompatibleClientV2") as mock_client:
|
||||
|
|
@ -210,7 +209,7 @@ class RegisterTest(test_util.ConfigTestCase):
|
|||
with mock.patch("certbot._internal.eff.handle_subscription") as mock_handle:
|
||||
mock_client().new_account_and_tos.side_effect = [mx_err, mock.MagicMock()]
|
||||
self.assertRaises(messages.Error, self._call)
|
||||
self.assertFalse(mock_handle.called)
|
||||
self.assertIs(mock_handle.called, False)
|
||||
|
||||
|
||||
class ClientTestCommon(test_util.ConfigTestCase):
|
||||
|
|
@ -247,7 +246,7 @@ class ClientTest(ClientTestCommon):
|
|||
|
||||
def test_init_acme_verify_ssl(self):
|
||||
net = self.acme_client.call_args[0][0]
|
||||
self.assertTrue(net.verify_ssl)
|
||||
self.assertIs(net.verify_ssl, True)
|
||||
|
||||
def _mock_obtain_certificate(self):
|
||||
self.client.auth_handler = mock.MagicMock()
|
||||
|
|
@ -609,7 +608,7 @@ class EnhanceConfigTest(ClientTestCommon):
|
|||
def test_already_exists_header(self, mock_log):
|
||||
self.config.hsts = True
|
||||
self._test_with_already_existing()
|
||||
self.assertTrue(mock_log.warning.called)
|
||||
self.assertIs(mock_log.warning.called, True)
|
||||
self.assertEqual(mock_log.warning.call_args[0][1],
|
||||
'Strict-Transport-Security')
|
||||
|
||||
|
|
@ -617,7 +616,7 @@ class EnhanceConfigTest(ClientTestCommon):
|
|||
def test_already_exists_redirect(self, mock_log):
|
||||
self.config.redirect = True
|
||||
self._test_with_already_existing()
|
||||
self.assertTrue(mock_log.warning.called)
|
||||
self.assertIs(mock_log.warning.called, True)
|
||||
self.assertEqual(mock_log.warning.call_args[0][1],
|
||||
'redirect')
|
||||
|
||||
|
|
@ -625,13 +624,13 @@ class EnhanceConfigTest(ClientTestCommon):
|
|||
def test_config_set_no_warning_redirect(self, mock_log):
|
||||
self.config.redirect = False
|
||||
self._test_with_already_existing()
|
||||
self.assertFalse(mock_log.warning.called)
|
||||
self.assertIs(mock_log.warning.called, False)
|
||||
|
||||
@mock.patch("certbot._internal.client.logger")
|
||||
def test_no_warn_redirect(self, mock_log):
|
||||
self.config.redirect = None
|
||||
self._test_with_all_supported()
|
||||
self.assertFalse(mock_log.warning.called)
|
||||
self.assertIs(mock_log.warning.called, False)
|
||||
|
||||
def test_no_ask_hsts(self):
|
||||
self.config.hsts = True
|
||||
|
|
@ -684,7 +683,7 @@ class EnhanceConfigTest(ClientTestCommon):
|
|||
|
||||
def _test_error_with_rollback(self):
|
||||
self._test_error()
|
||||
self.assertTrue(self.client.installer.restart.called)
|
||||
self.assertIs(self.client.installer.restart.called, True)
|
||||
|
||||
def _test_error(self):
|
||||
self.config.redirect = True
|
||||
|
|
|
|||
|
|
@ -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.warning.called)
|
||||
|
||||
@mock.patch("certbot._internal.hooks.logger")
|
||||
|
|
@ -352,8 +352,8 @@ class DeployHookTest(RenewalHookTest):
|
|||
self.config.deploy_hook = None
|
||||
mock_execute = self._call_with_mock_execute(
|
||||
self.config, ["example.org"], "/foo/bar")
|
||||
self.assertFalse(mock_execute.called)
|
||||
self.assertFalse(mock_logger.info.called)
|
||||
self.assertIs(mock_execute.called, False)
|
||||
self.assertIs(mock_logger.info.called, False)
|
||||
|
||||
def test_success(self):
|
||||
domains = ["example.org", "example.net"]
|
||||
|
|
@ -392,7 +392,7 @@ class RenewHookTest(RenewalHookTest):
|
|||
self.config.dry_run = True
|
||||
mock_execute = self._call_with_mock_execute(
|
||||
self.config, ["example.org"], "/foo/bar")
|
||||
self.assertFalse(mock_execute.called)
|
||||
self.assertIs(mock_execute.called, False)
|
||||
self.assertEqual(mock_logger.warning.call_count, 2)
|
||||
|
||||
def test_no_hooks(self):
|
||||
|
|
@ -402,8 +402,8 @@ class RenewHookTest(RenewalHookTest):
|
|||
with mock.patch("certbot._internal.hooks.logger") as mock_logger:
|
||||
mock_execute = self._call_with_mock_execute(
|
||||
self.config, ["example.org"], "/foo/bar")
|
||||
self.assertFalse(mock_execute.called)
|
||||
self.assertFalse(mock_logger.info.called)
|
||||
self.assertIs(mock_execute.called, False)
|
||||
self.assertIs(mock_logger.info.called, False)
|
||||
|
||||
def test_overlap(self):
|
||||
self.config.renew_hook = self.dir_hook
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -211,20 +211,20 @@ class CredentialsConfigurationRequireTest(test_util.TempDirTestCase):
|
|||
class DomainNameGuessTest(unittest.TestCase):
|
||||
|
||||
def test_simple_case(self):
|
||||
self.assertTrue(
|
||||
'example.com' in
|
||||
self.assertIn(
|
||||
'example.com',
|
||||
dns_common.base_domain_name_guesses("example.com")
|
||||
)
|
||||
|
||||
def test_sub_domain(self):
|
||||
self.assertTrue(
|
||||
'example.com' in
|
||||
self.assertIn(
|
||||
'example.com',
|
||||
dns_common.base_domain_name_guesses("foo.bar.baz.example.com")
|
||||
)
|
||||
|
||||
def test_second_level_domain(self):
|
||||
self.assertTrue(
|
||||
'example.co.uk' in
|
||||
self.assertIn(
|
||||
'example.co.uk',
|
||||
dns_common.base_domain_name_guesses("foo.bar.baz.example.co.uk")
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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,7 +349,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase):
|
|||
with mock.patch("certbot.util.logger.warning") as mock_warn:
|
||||
self.parser.parse_args(["--old-option"])
|
||||
self.assertEqual(mock_warn.call_count, 1)
|
||||
self.assertTrue("is deprecated" in mock_warn.call_args[0][0])
|
||||
self.assertIn("is deprecated", mock_warn.call_args[0][0])
|
||||
self.assertEqual("--old-option", mock_warn.call_args[0][1])
|
||||
|
||||
def test_warning_with_arg(self):
|
||||
|
|
@ -357,7 +357,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase):
|
|||
with mock.patch("certbot.util.logger.warning") as mock_warn:
|
||||
self.parser.parse_args(["--old-option", "42"])
|
||||
self.assertEqual(mock_warn.call_count, 1)
|
||||
self.assertTrue("is deprecated" in mock_warn.call_args[0][0])
|
||||
self.assertIn("is deprecated", mock_warn.call_args[0][0])
|
||||
self.assertEqual("--old-option", mock_warn.call_args[0][1])
|
||||
|
||||
def test_help(self):
|
||||
|
|
@ -368,7 +368,7 @@ class AddDeprecatedArgumentTest(unittest.TestCase):
|
|||
self.parser.parse_args(["-h"])
|
||||
except SystemExit:
|
||||
pass
|
||||
self.assertTrue("--old-option" not in stdout.getvalue())
|
||||
self.assertNotIn("--old-option", stdout.getvalue())
|
||||
|
||||
def test_set_constant(self):
|
||||
"""Test when ACTION_TYPES_THAT_DONT_NEED_A_VALUE is a set.
|
||||
|
|
@ -519,7 +519,7 @@ class OsInfoTest(unittest.TestCase):
|
|||
m_distro.like.return_value = "first debian third"
|
||||
id_likes = cbutil.get_systemd_os_like()
|
||||
self.assertEqual(len(id_likes), 3)
|
||||
self.assertTrue("debian" in id_likes)
|
||||
self.assertIn("debian", id_likes)
|
||||
|
||||
@mock.patch("certbot.util.distro")
|
||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||
|
|
@ -610,7 +610,7 @@ class AtexitRegisterTest(unittest.TestCase):
|
|||
|
||||
def test_not_called(self):
|
||||
self._test_common(initial_pid=-1)
|
||||
self.assertFalse(self.func.called)
|
||||
self.assertIs(self.func.called, False)
|
||||
|
||||
def _test_common(self, initial_pid):
|
||||
with mock.patch('certbot.util._INITIAL_PID', initial_pid):
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue