Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/certbot/certbot.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Julian <chris@zero1many.net>2017-09-16 03:10:43 +0300
committerBrad Warren <bmw@users.noreply.github.com>2017-09-16 03:10:43 +0300
commitf0caf5b04fc33d7b08d480d5ee2bd67603081834 (patch)
treee2bcc92b2135cdea4a3631a119c9617a598e6642
parentf6be07da74c664b57ac8c053585f919c79f9af44 (diff)
#4435. CLI Argument Default Organization (#5037)
* Enhancement #4435. Organizing defaults in prepare_and_parse_args() * Playing fast and loose with tox. Discovered screwy case involving flag_default returning empty list (domains) * Setting defaults for more low-hanging fruit. Some caveats remain. * key_path default to None * Applying PR feedback: explicit defaults even where redundant * Obsessive quote consistency * Set testing config path arguments to a 'certonly' default * Copy the default domains list rather than get reference * Build a testing Config from CLI_DEFAULTS * Update some email tests for use with defaults in config. config.email and config.noninteractive_mode in these tests used to be magic-mock'd, so were True-ish. The default email is now None and default noninteractive_mode is False, so update in tests accordingly. * Lint... * Copy anything retrieved using flag_defaults. Apply this to test_cli_ini_domains too. * Put those quotes back. Backslashes are just the worst. * Remove vestigial line * A test to ensure no regressions around modifying CLI_DEFAULTS
-rw-r--r--certbot/cli.py204
-rw-r--r--certbot/constants.py88
-rw-r--r--certbot/tests/cli_test.py19
-rw-r--r--certbot/tests/client_test.py2
-rw-r--r--certbot/tests/util.py15
5 files changed, 231 insertions, 97 deletions
diff --git a/certbot/cli.py b/certbot/cli.py
index afebbb7cb..9d17c7a25 100644
--- a/certbot/cli.py
+++ b/certbot/cli.py
@@ -282,7 +282,7 @@ def flag_default(name):
# argparse has been set up; it is not accurate for all flags. Call it
# with caution. Plugin defaults are missing, and some things are using
# defaults defined in this file, not in constants.py :(
- return constants.CLI_DEFAULTS[name]
+ return copy.deepcopy(constants.CLI_DEFAULTS[name])
def config_help(name, hidden=False):
@@ -866,9 +866,10 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
"e.g. -vvv.")
helpful.add(
None, "-t", "--text", dest="text_mode", action="store_true",
- help=argparse.SUPPRESS)
+ default=flag_default("text_mode"), help=argparse.SUPPRESS)
helpful.add(
- None, "--max-log-backups", type=nonnegative_int, default=1000,
+ None, "--max-log-backups", type=nonnegative_int,
+ default=flag_default("max_log_backups"),
help="Specifies the maximum number of backup logs that should "
"be kept by Certbot's built in log rotation. Setting this "
"flag to 0 disables log rotation entirely, causing "
@@ -876,19 +877,22 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
helpful.add(
[None, "automation", "run", "certonly"], "-n", "--non-interactive", "--noninteractive",
dest="noninteractive_mode", action="store_true",
+ default=flag_default("noninteractive_mode"),
help="Run without ever asking for user input. This may require "
"additional command line flags; the client will try to explain "
"which ones are required if it finds one missing")
helpful.add(
[None, "register", "run", "certonly"],
constants.FORCE_INTERACTIVE_FLAG, action="store_true",
+ default=flag_default("force_interactive"),
help="Force Certbot to be interactive even if it detects it's not "
"being run in a terminal. This flag cannot be used with the "
"renew subcommand.")
helpful.add(
[None, "run", "certonly", "certificates"],
"-d", "--domains", "--domain", dest="domains",
- metavar="DOMAIN", action=_DomainsAction, default=[],
+ metavar="DOMAIN", action=_DomainsAction,
+ default=flag_default("domains"),
help="Domain names to apply. For multiple domains you can use "
"multiple -d flags or enter a comma separated list of domains "
"as a parameter. The first provided domain will be used in "
@@ -899,7 +903,7 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
helpful.add(
[None, "run", "certonly", "manage", "delete", "certificates", "renew"],
"--cert-name", dest="certname",
- metavar="CERTNAME", default=None,
+ metavar="CERTNAME", default=flag_default("certname"),
help="Certificate name to apply. This name is used by Certbot for housekeeping "
"and in file paths; it doesn't affect the content of the certificate itself. "
"To see certificate names, run 'certbot certificates'. "
@@ -909,6 +913,7 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
helpful.add(
[None, "testing", "renew", "certonly"],
"--dry-run", action="store_true", dest="dry_run",
+ default=flag_default("dry_run"),
help="Perform a test run of the client, obtaining test (invalid) certificates"
" but not saving them to disk. This can currently only be used"
" with the 'certonly' and 'renew' subcommands. \nNote: Although --dry-run"
@@ -921,6 +926,7 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
" renewal. --deploy-hook commands are not called.")
helpful.add(
["register", "automation"], "--register-unsafely-without-email", action="store_true",
+ default=flag_default("register_unsafely_without_email"),
help="Specifying this flag enables registering an account with no "
"email address. This is strongly discouraged, because in the "
"event of key loss or account compromise you will irrevocably "
@@ -931,27 +937,29 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
"update to the web site.")
helpful.add(
"register", "--update-registration", action="store_true",
+ default=flag_default("update_registration"),
help="With the register verb, indicates that details associated "
"with an existing registration, such as the e-mail address, "
"should be updated, rather than registering a new account.")
helpful.add(
["register", "unregister", "automation"], "-m", "--email",
+ default=flag_default("email"),
help=config_help("email"))
helpful.add(["register", "automation"], "--eff-email", action="store_true",
- default=None, dest="eff_email",
+ default=flag_default("eff_email"), dest="eff_email",
help="Share your e-mail address with EFF")
helpful.add(["register", "automation"], "--no-eff-email", action="store_false",
- default=None, dest="eff_email",
+ default=flag_default("eff_email"), dest="eff_email",
help="Don't share your e-mail address with EFF")
helpful.add(
["automation", "certonly", "run"],
"--keep-until-expiring", "--keep", "--reinstall",
- dest="reinstall", action="store_true",
+ dest="reinstall", action="store_true", default=flag_default("reinstall"),
help="If the requested certificate matches an existing certificate, always keep the "
"existing one until it is due for renewal (for the "
"'run' subcommand this means reinstall the existing certificate). (default: Ask)")
helpful.add(
- "automation", "--expand", action="store_true",
+ "automation", "--expand", action="store_true", default=flag_default("expand"),
help="If an existing certificate is a strict subset of the requested names, "
"always expand and replace it with the additional names. (default: Ask)")
helpful.add(
@@ -960,21 +968,24 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
help="show program's version number and exit")
helpful.add(
["automation", "renew"],
- "--force-renewal", "--renew-by-default",
- action="store_true", dest="renew_by_default", help="If a certificate "
+ "--force-renewal", "--renew-by-default", dest="renew_by_default",
+ action="store_true", default=flag_default("renew_by_default"),
+ help="If a certificate "
"already exists for the requested domains, renew it now, "
"regardless of whether it is near expiry. (Often "
"--keep-until-expiring is more appropriate). Also implies "
"--expand.")
helpful.add(
- "automation", "--renew-with-new-domains",
- action="store_true", dest="renew_with_new_domains", help="If a "
+ "automation", "--renew-with-new-domains", dest="renew_with_new_domains",
+ action="store_true", default=flag_default("renew_with_new_domains"),
+ help="If a "
"certificate already exists for the requested certificate name "
"but does not match the requested domains, renew it now, "
"regardless of whether it is near expiry.")
helpful.add(
["automation", "renew", "certonly"],
"--allow-subset-of-names", action="store_true",
+ default=flag_default("allow_subset_of_names"),
help="When performing domain validation, do not consider it a failure "
"if authorizations can not be obtained for a strict subset of "
"the requested domains. This may be useful for allowing renewals for "
@@ -982,39 +993,46 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
"at this system. This option cannot be used with --csr.")
helpful.add(
"automation", "--agree-tos", dest="tos", action="store_true",
+ default=flag_default("tos"),
help="Agree to the ACME Subscriber Agreement (default: Ask)")
helpful.add(
["unregister", "automation"], "--account", metavar="ACCOUNT_ID",
+ default=flag_default("account"),
help="Account ID to use")
helpful.add(
"automation", "--duplicate", dest="duplicate", action="store_true",
+ default=flag_default("duplicate"),
help="Allow making a certificate lineage that duplicates an existing one "
"(both can be renewed in parallel)")
helpful.add(
"automation", "--os-packages-only", action="store_true",
+ default=flag_default("os_packages_only"),
help="(certbot-auto only) install OS package dependencies and then stop")
helpful.add(
"automation", "--no-self-upgrade", action="store_true",
+ default=flag_default("no_self_upgrade"),
help="(certbot-auto only) prevent the certbot-auto script from"
" upgrading itself to newer released versions (default: Upgrade"
" automatically)")
helpful.add(
"automation", "--no-bootstrap", action="store_true",
+ default=flag_default("no_bootstrap"),
help="(certbot-auto only) prevent the certbot-auto script from"
" installing OS-level dependencies (default: Prompt to install "
" OS-wide dependencies, but exit if the user says 'No')")
helpful.add(
["automation", "renew", "certonly", "run"],
"-q", "--quiet", dest="quiet", action="store_true",
+ default=flag_default("quiet"),
help="Silence all output except errors. Useful for automation via cron."
" Implies --non-interactive.")
# overwrites server, handled in HelpfulArgumentParser.parse_args()
helpful.add(["testing", "revoke", "run"], "--test-cert", "--staging",
- action='store_true', dest='staging',
- help='Use the staging server to obtain or revoke test (invalid) certificates; equivalent'
- ' to --server ' + constants.STAGING_URI)
+ dest="staging", action="store_true", default=flag_default("staging"),
+ help="Use the staging server to obtain or revoke test (invalid) certificates; equivalent"
+ " to --server " + constants.STAGING_URI)
helpful.add(
- "testing", "--debug", action="store_true",
+ "testing", "--debug", action="store_true", default=flag_default("debug"),
help="Show tracebacks in case of errors, and allow certbot-auto "
"execution on experimental platforms")
helpful.add(
@@ -1044,6 +1062,7 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
default=flag_default("http01_address"), help=config_help("http01_address"))
helpful.add(
"testing", "--break-my-certs", action="store_true",
+ default=flag_default("break_my_certs"),
help="Be willing to replace or renew valid certificates with invalid "
"(testing/staging) certificates")
helpful.add(
@@ -1051,47 +1070,51 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
default=flag_default("rsa_key_size"), help=config_help("rsa_key_size"))
helpful.add(
"security", "--must-staple", action="store_true",
- help=config_help("must_staple"), dest="must_staple", default=False)
+ dest="must_staple", default=flag_default("must_staple"),
+ help=config_help("must_staple"))
helpful.add(
- "security", "--redirect", action="store_true",
+ "security", "--redirect", action="store_true", dest="redirect",
+ default=flag_default("redirect"),
help="Automatically redirect all HTTP traffic to HTTPS for the newly "
- "authenticated vhost. (default: Ask)", dest="redirect", default=None)
+ "authenticated vhost. (default: Ask)")
helpful.add(
- "security", "--no-redirect", action="store_false",
+ "security", "--no-redirect", action="store_false", dest="redirect",
+ default=flag_default("redirect"),
help="Do not automatically redirect all HTTP traffic to HTTPS for the newly "
- "authenticated vhost. (default: Ask)", dest="redirect", default=None)
+ "authenticated vhost. (default: Ask)")
helpful.add(
- "security", "--hsts", action="store_true",
+ "security", "--hsts", action="store_true", dest="hsts", default=flag_default("hsts"),
help="Add the Strict-Transport-Security header to every HTTP response."
" Forcing browser to always use SSL for the domain."
- " Defends against SSL Stripping.", dest="hsts", default=False)
+ " Defends against SSL Stripping.")
helpful.add(
- "security", "--no-hsts", action="store_false",
- help=argparse.SUPPRESS, dest="hsts", default=False)
+ "security", "--no-hsts", action="store_false", dest="hsts",
+ default=flag_default("hsts"), help=argparse.SUPPRESS)
helpful.add(
- "security", "--uir", action="store_true",
- help="Add the \"Content-Security-Policy: upgrade-insecure-requests\""
- " header to every HTTP response. Forcing the browser to use"
- " https:// for every http:// resource.", dest="uir", default=None)
+ "security", "--uir", action="store_true", dest="uir", default=flag_default("uir"),
+ help='Add the "Content-Security-Policy: upgrade-insecure-requests"'
+ ' header to every HTTP response. Forcing the browser to use'
+ ' https:// for every http:// resource.')
helpful.add(
- "security", "--no-uir", action="store_false",
- help=argparse.SUPPRESS, dest="uir", default=None)
+ "security", "--no-uir", action="store_false", dest="uir", default=flag_default("uir"),
+ help=argparse.SUPPRESS)
helpful.add(
- "security", "--staple-ocsp", action="store_true",
+ "security", "--staple-ocsp", action="store_true", dest="staple",
+ default=flag_default("staple"),
help="Enables OCSP Stapling. A valid OCSP response is stapled to"
- " the certificate that the server offers during TLS.",
- dest="staple", default=None)
+ " the certificate that the server offers during TLS.")
helpful.add(
- "security", "--no-staple-ocsp", action="store_false",
- help=argparse.SUPPRESS, dest="staple", default=None)
+ "security", "--no-staple-ocsp", action="store_false", dest="staple",
+ default=flag_default("staple"), help=argparse.SUPPRESS)
helpful.add(
"security", "--strict-permissions", action="store_true",
+ default=flag_default("strict_permissions"),
help="Require that all configuration files are owned by the current "
"user; only needed if your config is somewhere unsafe like /tmp/")
helpful.add(
["manual", "standalone", "certonly", "renew"],
"--preferred-challenges", dest="pref_challs",
- action=_PrefChallAction, default=[],
+ action=_PrefChallAction, default=flag_default("pref_challs"),
help='A sorted, comma delimited list of the preferred challenge to '
'use during authorization with the most preferred challenge '
'listed first (Eg, "dns" or "tls-sni-01,http,dns"). '
@@ -1120,17 +1143,18 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
action=_RenewHookAction, help=argparse.SUPPRESS)
helpful.add(
"renew", "--deploy-hook", action=_DeployHookAction,
- help="Command to be run in a shell once for each successfully"
- " issued certificate. For this command, the shell variable"
- " $RENEWED_LINEAGE will point to the config live subdirectory"
+ help='Command to be run in a shell once for each successfully'
+ ' issued certificate. For this command, the shell variable'
+ ' $RENEWED_LINEAGE will point to the config live subdirectory'
' (for example, "/etc/letsencrypt/live/example.com") containing'
- " the new certificates and keys; the shell variable"
- " $RENEWED_DOMAINS will contain a space-delimited list of"
+ ' the new certificates and keys; the shell variable'
+ ' $RENEWED_DOMAINS will contain a space-delimited list of'
' renewed certificate domains (for example, "example.com'
' www.example.com"')
helpful.add(
"renew", "--disable-hook-validation",
- action='store_false', dest='validate_hooks', default=True,
+ action="store_false", dest="validate_hooks",
+ default=flag_default("validate_hooks"),
help="Ordinarily the commands specified for"
" --pre-hook/--post-hook/--deploy-hook will be checked for"
" validity, to see if the programs being run are in the $PATH,"
@@ -1156,48 +1180,53 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): # pylint: dis
def _create_subparsers(helpful):
- helpful.add("config_changes", "--num", type=int,
+ helpful.add("config_changes", "--num", type=int, default=flag_default("num"),
help="How many past revisions you want to be displayed")
from certbot.client import sample_user_agent # avoid import loops
helpful.add(
- None, "--user-agent", default=None,
- help="Set a custom user agent string for the client. User agent strings allow "
- "the CA to collect high level statistics about success rates by OS, "
- "plugin and use case, and to know when to deprecate support for past Python "
+ None, "--user-agent", default=flag_default("user_agent"),
+ help='Set a custom user agent string for the client. User agent strings allow '
+ 'the CA to collect high level statistics about success rates by OS, '
+ 'plugin and use 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: {0}). The flags encoded in the user agent are: '
'--duplicate, --force-renew, --allow-subset-of-names, -n, and '
'whether any hooks are set.'.format(sample_user_agent()))
helpful.add(
- None, "--user-agent-comment", default=None, type=_user_agent_comment_type,
+ None, "--user-agent-comment", default=flag_default("user_agent_comment"),
+ type=_user_agent_comment_type,
help="Add a comment to the default user agent string. May be used when repackaging Certbot "
"or calling it from another tool to allow additional statistical data to be collected."
" Ignored if --user-agent is set. (Example: Foo-Wrapper/1.0)")
helpful.add("certonly",
- "--csr", type=read_file,
+ "--csr", default=flag_default("csr"), type=read_file,
help="Path to a Certificate Signing Request (CSR) in DER or PEM format."
" Currently --csr only works with the 'certonly' subcommand.")
helpful.add("revoke",
"--reason", dest="reason",
choices=CaseInsensitiveList(sorted(constants.REVOCATION_REASONS,
key=constants.REVOCATION_REASONS.get)),
- action=_EncodeReasonAction, default=0,
+ action=_EncodeReasonAction, default=flag_default("reason"),
help="Specify reason for revoking certificate. (default: unspecified)")
helpful.add("rollback",
"--checkpoints", type=int, metavar="N",
default=flag_default("rollback_checkpoints"),
help="Revert configuration N number of checkpoints.")
helpful.add("plugins",
- "--init", action="store_true", help="Initialize plugins.")
+ "--init", action="store_true", default=flag_default("init"),
+ help="Initialize plugins.")
helpful.add("plugins",
- "--prepare", action="store_true", help="Initialize and prepare plugins.")
+ "--prepare", action="store_true", default=flag_default("prepare"),
+ help="Initialize and prepare plugins.")
helpful.add("plugins",
"--authenticators", action="append_const", dest="ifaces",
+ default=flag_default("ifaces"),
const=interfaces.IAuthenticator, help="Limit to authenticator plugins only.")
helpful.add("plugins",
"--installers", action="append_const", dest="ifaces",
+ default=flag_default("ifaces"),
const=interfaces.IInstaller, help="Limit to installer plugins only.")
@@ -1263,53 +1292,68 @@ def _plugins_parsing(helpful, plugins):
"a particular plugin by setting options provided below. Running "
"--help <plugin_name> will list flags specific to that plugin.")
- helpful.add("plugins", "--configurator",
+ helpful.add("plugins", "--configurator", default=flag_default("configurator"),
help="Name of the plugin that is both an authenticator and an installer."
" Should not be used together with --authenticator or --installer. "
"(default: Ask)")
- helpful.add("plugins", "-a", "--authenticator", help="Authenticator plugin name.")
- helpful.add("plugins", "-i", "--installer",
+ helpful.add("plugins", "-a", "--authenticator", default=flag_default("authenticator"),
+ help="Authenticator plugin name.")
+ helpful.add("plugins", "-i", "--installer", default=flag_default("installer"),
help="Installer plugin name (also used to find domains).")
helpful.add(["plugins", "certonly", "run", "install", "config_changes"],
- "--apache", action="store_true",
+ "--apache", action="store_true", default=flag_default("apache"),
help="Obtain and install certificates using Apache")
helpful.add(["plugins", "certonly", "run", "install", "config_changes"],
- "--nginx", action="store_true", help="Obtain and install certificates using Nginx")
+ "--nginx", action="store_true", default=flag_default("nginx"),
+ help="Obtain and install certificates using Nginx")
helpful.add(["plugins", "certonly"], "--standalone", action="store_true",
+ default=flag_default("standalone"),
help='Obtain certificates using a "standalone" webserver.')
helpful.add(["plugins", "certonly"], "--manual", action="store_true",
- help='Provide laborious manual instructions for obtaining a certificate')
+ default=flag_default("manual"),
+ help="Provide laborious manual instructions for obtaining a certificate")
helpful.add(["plugins", "certonly"], "--webroot", action="store_true",
- help='Obtain certificates by placing files in a webroot directory.')
+ default=flag_default("webroot"),
+ help="Obtain certificates by placing files in a webroot directory.")
helpful.add(["plugins", "certonly"], "--dns-cloudflare", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are '
- 'using Cloudflare for DNS).'))
+ default=flag_default("dns_cloudflare"),
+ help=("Obtain certificates using a DNS TXT record (if you are "
+ "using Cloudflare for DNS)."))
helpful.add(["plugins", "certonly"], "--dns-cloudxns", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are '
- 'using CloudXNS for DNS).'))
+ default=flag_default("dns_cloudxns"),
+ help=("Obtain certificates using a DNS TXT record (if you are "
+ "using CloudXNS for DNS)."))
helpful.add(["plugins", "certonly"], "--dns-digitalocean", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are '
- 'using DigitalOcean for DNS).'))
+ default=flag_default("dns_digitalocean"),
+ help=("Obtain certificates using a DNS TXT record (if you are "
+ "using DigitalOcean for DNS)."))
helpful.add(["plugins", "certonly"], "--dns-dnsimple", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are '
- 'using DNSimple for DNS).'))
+ default=flag_default("dns_dnsimple"),
+ help=("Obtain certificates using a DNS TXT record (if you are "
+ "using DNSimple for DNS)."))
helpful.add(["plugins", "certonly"], "--dns-dnsmadeeasy", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are'
- 'using DNS Made Easy for DNS).'))
+ default=flag_default("dns_dnsmadeeasy"),
+ help=("Obtain certificates using a DNS TXT record (if you are"
+ "using DNS Made Easy for DNS)."))
helpful.add(["plugins", "certonly"], "--dns-google", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are '
- 'using Google Cloud DNS).'))
+ default=flag_default("dns_google"),
+ help=("Obtain certificates using a DNS TXT record (if you are "
+ "using Google Cloud DNS)."))
helpful.add(["plugins", "certonly"], "--dns-luadns", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are '
- 'using LuaDNS for DNS).'))
+ default=flag_default("dns_luadns"),
+ help=("Obtain certificates using a DNS TXT record (if you are "
+ "using LuaDNS for DNS)."))
helpful.add(["plugins", "certonly"], "--dns-nsone", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are '
- 'using NS1 for DNS).'))
+ default=flag_default("dns_nsone"),
+ help=("Obtain certificates using a DNS TXT record (if you are "
+ "using NS1 for DNS)."))
helpful.add(["plugins", "certonly"], "--dns-rfc2136", action="store_true",
- help='Obtain certificates using a DNS TXT record (if you are using BIND for DNS).')
+ default=flag_default("dns_rfc2136"),
+ help="Obtain certificates using a DNS TXT record (if you are using BIND for DNS).")
helpful.add(["plugins", "certonly"], "--dns-route53", action="store_true",
- help=('Obtain certificates using a DNS TXT record (if you are using Route53 for '
- 'DNS).'))
+ default=flag_default("dns_route53"),
+ help=("Obtain certificates using a DNS TXT record (if you are using Route53 for "
+ "DNS)."))
# things should not be reorder past/pre this comment:
# plugins_group should be displayed in --help before plugin
diff --git a/certbot/constants.py b/certbot/constants.py
index 557ccd4c6..cae9864a9 100644
--- a/certbot/constants.py
+++ b/certbot/constants.py
@@ -19,23 +19,91 @@ CLI_DEFAULTS = dict(
os.path.join(os.environ.get("XDG_CONFIG_HOME", "~/.config"),
"letsencrypt", "cli.ini"),
],
+
+ # Main parser
verbose_count=-int(logging.INFO / 10),
- server="https://acme-v01.api.letsencrypt.org/directory",
- rsa_key_size=2048,
- rollback_checkpoints=1,
- config_dir="/etc/letsencrypt",
- work_dir="/var/lib/letsencrypt",
- logs_dir="/var/log/letsencrypt",
+ text_mode=False,
+ max_log_backups=1000,
+ noninteractive_mode=False,
+ force_interactive=False,
+ domains=[],
+ certname=None,
+ dry_run=False,
+ register_unsafely_without_email=False,
+ update_registration=False,
+ email=None,
+ eff_email=None,
+ reinstall=False,
+ expand=False,
+ renew_by_default=False,
+ renew_with_new_domains=False,
+ allow_subset_of_names=False,
+ tos=False,
+ account=None,
+ duplicate=False,
+ os_packages_only=False,
+ no_self_upgrade=False,
+ no_bootstrap=False,
+ quiet=False,
+ staging=False,
+ debug=False,
+ debug_challenges=False,
no_verify_ssl=False,
- http01_port=challenges.HTTP01Response.PORT,
- http01_address="",
tls_sni_01_port=challenges.TLSSNI01Response.PORT,
tls_sni_01_address="",
+ http01_port=challenges.HTTP01Response.PORT,
+ http01_address="",
+ break_my_certs=False,
+ rsa_key_size=2048,
+ must_staple=False,
+ redirect=None,
+ hsts=None,
+ uir=None,
+ staple=None,
+ strict_permissions=False,
+ pref_challs=[],
+ validate_hooks=True,
+
+ # Subparsers
+ num=None,
+ user_agent=None,
+ user_agent_comment=None,
+ csr=None,
+ reason=0,
+ rollback_checkpoints=1,
+ init=False,
+ prepare=False,
+ ifaces=None,
+ # Path parsers
auth_cert_path="./cert.pem",
auth_chain_path="./chain.pem",
- strict_permissions=False,
- debug_challenges=False,
+ key_path=None,
+ config_dir="/etc/letsencrypt",
+ work_dir="/var/lib/letsencrypt",
+ logs_dir="/var/log/letsencrypt",
+ server="https://acme-v01.api.letsencrypt.org/directory",
+
+ # Plugins parsers
+ configurator=None,
+ authenticator=None,
+ installer=None,
+ apache=False,
+ nginx=False,
+ standalone=False,
+ manual=False,
+ webroot=False,
+ dns_cloudflare=False,
+ dns_cloudxns=False,
+ dns_digitalocean=False,
+ dns_dnsimple=False,
+ dns_dnsmadeeasy=False,
+ dns_google=False,
+ dns_luadns=False,
+ dns_nsone=False,
+ dns_rfc2136=False,
+ dns_route53=False
+
)
STAGING_URI = "https://acme-staging.api.letsencrypt.org/directory"
diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py
index 1a3742348..e887e3043 100644
--- a/certbot/tests/cli_test.py
+++ b/certbot/tests/cli_test.py
@@ -3,6 +3,7 @@ import argparse
import unittest
import os
import tempfile
+import copy
import mock
import six
@@ -81,7 +82,11 @@ class ParseTest(unittest.TestCase): # pylint: disable=too-many-public-methods
def test_cli_ini_domains(self, mock_flag_default):
tmp_config = tempfile.NamedTemporaryFile()
# use a shim to get ConfigArgParse to pick up tmp_config
- shim = lambda v: constants.CLI_DEFAULTS[v] if v != "config_files" else [tmp_config.name]
+ shim = (
+ lambda v: copy.deepcopy(constants.CLI_DEFAULTS[v])
+ if v != "config_files"
+ else [tmp_config.name]
+ )
mock_flag_default.side_effect = shim
namespace = self.parse(["certonly"])
@@ -391,6 +396,18 @@ class ParseTest(unittest.TestCase): # pylint: disable=too-many-public-methods
namespace = self.parse(["--max-log-backups", value])
self.assertEqual(namespace.max_log_backups, int(value))
+ def test_unchanging_defaults(self):
+ namespace = self.parse([])
+ self.assertEqual(namespace.domains, [])
+ self.assertEqual(namespace.pref_challs, [])
+
+ namespace.pref_challs = [challenges.HTTP01.typ]
+ namespace.domains = ['example.com']
+
+ namespace = self.parse([])
+ self.assertEqual(namespace.domains, [])
+ self.assertEqual(namespace.pref_challs, [])
+
class DefaultTest(unittest.TestCase):
"""Tests for certbot.cli._Default."""
diff --git a/certbot/tests/client_test.py b/certbot/tests/client_test.py
index 2416acf95..09c4a50ca 100644
--- a/certbot/tests/client_test.py
+++ b/certbot/tests/client_test.py
@@ -28,6 +28,7 @@ class RegisterTest(test_util.ConfigTestCase):
super(RegisterTest, self).setUp()
self.config.rsa_key_size = 1024
self.config.register_unsafely_without_email = False
+ self.config.email = "alias@example.com"
self.account_storage = account.AccountMemoryStorage()
self.tos_cb = mock.MagicMock()
@@ -75,6 +76,7 @@ class RegisterTest(test_util.ConfigTestCase):
@mock.patch("certbot.account.report_new_account")
def test_email_invalid_noninteractive(self, _rep):
from acme import messages
+ self.config.noninteractive_mode = True
msg = "DNS problem: NXDOMAIN looking up MX for example.com"
mx_err = messages.Error.with_code('invalidContact', detail=msg)
with mock.patch("certbot.client.acme_client.Client") as mock_client:
diff --git a/certbot/tests/util.py b/certbot/tests/util.py
index 698962516..73d002989 100644
--- a/certbot/tests/util.py
+++ b/certbot/tests/util.py
@@ -277,13 +277,16 @@ class ConfigTestCase(TempDirTestCase):
def setUp(self):
super(ConfigTestCase, self).setUp()
self.config = configuration.NamespaceConfig(
- mock.MagicMock(
- config_dir=os.path.join(self.tempdir, 'config'),
- work_dir=os.path.join(self.tempdir, 'work'),
- logs_dir=os.path.join(self.tempdir, 'logs'),
- server="example.com",
- )
+ mock.MagicMock(**constants.CLI_DEFAULTS)
)
+ self.config.verb = "certonly"
+ self.config.config_dir = os.path.join(self.tempdir, 'config')
+ self.config.work_dir = os.path.join(self.tempdir, 'work')
+ self.config.logs_dir = os.path.join(self.tempdir, 'logs')
+ self.config.cert_path = constants.CLI_DEFAULTS['auth_cert_path']
+ self.config.fullchain_path = constants.CLI_DEFAULTS['auth_chain_path']
+ self.config.chain_path = constants.CLI_DEFAULTS['auth_chain_path']
+ self.config.server = "example.com"
def lock_and_call(func, lock_path):
"""Grab a lock for lock_path and call func.