From 641e63b08c0f56583b63129489cd4ac2e32c591e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 1 May 2025 11:50:10 +0200 Subject: [PATCH] Replace % and str.format() with f-strings (#875) * Replace % and str.format() with f-strings. * Apply suggestions from review. --- plugins/action/openssl_privatekey_pipe.py | 4 +- plugins/filter/gpg_fingerprint.py | 4 +- plugins/filter/openssl_csr_info.py | 9 +- plugins/filter/openssl_privatekey_info.py | 8 +- plugins/filter/openssl_publickey_info.py | 3 +- plugins/filter/parse_serial.py | 4 +- plugins/filter/split_pem.py | 3 +- plugins/filter/to_serial.py | 4 +- plugins/filter/x509_certificate_info.py | 9 +- plugins/filter/x509_crl_info.py | 12 +- plugins/module_utils/acme/acme.py | 68 ++++------ .../module_utils/acme/backend_cryptography.py | 44 +++---- .../module_utils/acme/backend_openssl_cli.py | 81 +++++------- plugins/module_utils/acme/backends.py | 10 +- plugins/module_utils/acme/certificate.py | 46 ++----- plugins/module_utils/acme/certificates.py | 8 +- plugins/module_utils/acme/challenges.py | 39 ++---- plugins/module_utils/acme/errors.py | 74 ++++------- plugins/module_utils/acme/io.py | 16 +-- plugins/module_utils/acme/orders.py | 14 +- plugins/module_utils/acme/utils.py | 11 +- plugins/module_utils/crypto/_asn1.py | 5 +- plugins/module_utils/crypto/_objects.py | 8 +- .../crypto/cryptography_support.py | 124 ++++++------------ plugins/module_utils/crypto/math.py | 6 +- .../crypto/module_backends/certificate.py | 6 +- .../module_backends/certificate_acme.py | 8 +- .../module_backends/certificate_entrust.py | 24 +--- .../module_backends/certificate_info.py | 15 +-- .../module_backends/certificate_ownca.py | 13 +- .../module_backends/certificate_selfsigned.py | 13 +- .../crypto/module_backends/crl_info.py | 6 +- .../crypto/module_backends/csr.py | 27 ++-- .../crypto/module_backends/csr_info.py | 12 +- .../crypto/module_backends/privatekey.py | 30 ++--- .../module_backends/privatekey_convert.py | 16 +-- .../crypto/module_backends/privatekey_info.py | 10 +- .../crypto/module_backends/publickey_info.py | 11 +- plugins/module_utils/crypto/pem.py | 22 +--- plugins/module_utils/crypto/support.py | 29 ++-- plugins/module_utils/ecs/api.py | 38 ++---- plugins/module_utils/gnupg/cli.py | 10 +- plugins/module_utils/io.py | 12 +- .../module_utils/openssh/backends/common.py | 10 +- .../openssh/backends/keypair_backend.py | 7 +- plugins/module_utils/openssh/certificate.py | 45 +++---- plugins/module_utils/openssh/cryptography.py | 34 ++--- plugins/module_utils/openssh/utils.py | 30 ++--- plugins/module_utils/serial.py | 4 +- plugins/module_utils/time.py | 4 +- plugins/modules/acme_account.py | 5 +- plugins/modules/acme_account_info.py | 4 +- plugins/modules/acme_certificate.py | 28 ++-- .../acme_certificate_deactivate_authz.py | 4 +- .../modules/acme_certificate_order_create.py | 4 +- .../acme_certificate_order_validate.py | 24 ++-- .../modules/acme_certificate_renewal_info.py | 27 ++-- plugins/modules/acme_certificate_revoke.py | 4 +- plugins/modules/acme_challenge_cert_helper.py | 4 +- plugins/modules/certificate_complete_chain.py | 24 ++-- plugins/modules/ecs_certificate.py | 54 +++----- plugins/modules/ecs_domain.py | 14 +- plugins/modules/get_certificate.py | 35 ++--- plugins/modules/luks_device.py | 73 +++++------ plugins/modules/openssh_cert.py | 20 +-- plugins/modules/openssl_csr.py | 3 +- plugins/modules/openssl_csr_info.py | 4 +- plugins/modules/openssl_dhparam.py | 11 +- plugins/modules/openssl_pkcs12.py | 15 +-- plugins/modules/openssl_privatekey.py | 3 +- plugins/modules/openssl_privatekey_convert.py | 3 +- plugins/modules/openssl_privatekey_info.py | 3 +- plugins/modules/openssl_publickey.py | 11 +- plugins/modules/openssl_publickey_info.py | 3 +- plugins/modules/openssl_signature.py | 12 +- plugins/modules/openssl_signature_info.py | 13 +- plugins/modules/x509_certificate.py | 3 +- plugins/modules/x509_certificate_convert.py | 33 ++--- plugins/modules/x509_certificate_info.py | 10 +- plugins/modules/x509_crl.py | 30 ++--- plugins/modules/x509_crl_info.py | 8 +- plugins/plugin_utils/action_module.py | 18 +-- plugins/plugin_utils/gnupg.py | 9 +- .../plugins/module_utils/crypto/test_asn1.py | 8 +- .../crypto/test_cryptography_support.py | 4 +- .../module_utils/openssh/test_cryptography.py | 2 +- 86 files changed, 544 insertions(+), 1036 deletions(-) diff --git a/plugins/action/openssl_privatekey_pipe.py b/plugins/action/openssl_privatekey_pipe.py index d74fbe90..e46b05ed 100644 --- a/plugins/action/openssl_privatekey_pipe.py +++ b/plugins/action/openssl_privatekey_pipe.py @@ -32,9 +32,7 @@ class PrivateKeyModule: try: data = base64.b64decode(module.params["content"]) except Exception as e: - module.fail_json( - msg="Cannot decode Base64 encoded data: {0}".format(e) - ) + module.fail_json(msg=f"Cannot decode Base64 encoded data: {e}") else: data = to_bytes(module.params["content"]) module_backend.set_existing(data) diff --git a/plugins/filter/gpg_fingerprint.py b/plugins/filter/gpg_fingerprint.py index 24e682ff..147fcb26 100644 --- a/plugins/filter/gpg_fingerprint.py +++ b/plugins/filter/gpg_fingerprint.py @@ -54,9 +54,7 @@ from ansible_collections.community.crypto.plugins.plugin_utils.gnupg import ( def gpg_fingerprint(input): if not isinstance(input, string_types): raise AnsibleFilterError( - "The input for the community.crypto.gpg_fingerprint filter must be a string; got {type} instead".format( - type=type(input) - ) + f"The input for the community.crypto.gpg_fingerprint filter must be a string; got {type(input)} instead" ) try: gpg = PluginGPGRunner() diff --git a/plugins/filter/openssl_csr_info.py b/plugins/filter/openssl_csr_info.py index 8fa6909e..86f36053 100644 --- a/plugins/filter/openssl_csr_info.py +++ b/plugins/filter/openssl_csr_info.py @@ -292,19 +292,16 @@ def openssl_csr_info_filter(data, name_encoding="ignore"): """Extract information from X.509 PEM certificate.""" if not isinstance(data, string_types): raise AnsibleFilterError( - "The community.crypto.openssl_csr_info input must be a text type, not %s" - % type(data) + f"The community.crypto.openssl_csr_info input must be a text type, not {type(data)}" ) if not isinstance(name_encoding, string_types): raise AnsibleFilterError( - "The name_encoding option must be of a text type, not %s" - % type(name_encoding) + f"The name_encoding option must be of a text type, not {type(name_encoding)}" ) name_encoding = to_native(name_encoding) if name_encoding not in ("ignore", "idna", "unicode"): raise AnsibleFilterError( - 'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' - % name_encoding + f'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "{name_encoding}"' ) module = FilterModuleMock({"name_encoding": name_encoding}) diff --git a/plugins/filter/openssl_privatekey_info.py b/plugins/filter/openssl_privatekey_info.py index 467369e5..303194cd 100644 --- a/plugins/filter/openssl_privatekey_info.py +++ b/plugins/filter/openssl_privatekey_info.py @@ -167,17 +167,15 @@ def openssl_privatekey_info_filter( """Extract information from X.509 PEM certificate.""" if not isinstance(data, string_types): raise AnsibleFilterError( - "The community.crypto.openssl_privatekey_info input must be a text type, not %s" - % type(data) + f"The community.crypto.openssl_privatekey_info input must be a text type, not {type(data)}" ) if passphrase is not None and not isinstance(passphrase, string_types): raise AnsibleFilterError( - "The passphrase option must be a text type, not %s" % type(passphrase) + f"The passphrase option must be a text type, not {type(passphrase)}" ) if not isinstance(return_private_key_data, bool): raise AnsibleFilterError( - "The return_private_key_data option must be a boolean, not %s" - % type(return_private_key_data) + f"The return_private_key_data option must be a boolean, not {type(return_private_key_data)}" ) module = FilterModuleMock({}) diff --git a/plugins/filter/openssl_publickey_info.py b/plugins/filter/openssl_publickey_info.py index 4741adfd..b8a66790 100644 --- a/plugins/filter/openssl_publickey_info.py +++ b/plugins/filter/openssl_publickey_info.py @@ -142,8 +142,7 @@ def openssl_publickey_info_filter(data): """Extract information from OpenSSL PEM public key.""" if not isinstance(data, string_types): raise AnsibleFilterError( - "The community.crypto.openssl_publickey_info input must be a text type, not %s" - % type(data) + f"The community.crypto.openssl_publickey_info input must be a text type, not {type(data)}" ) module = FilterModuleMock({}) diff --git a/plugins/filter/parse_serial.py b/plugins/filter/parse_serial.py index 7c5ba4be..9a785557 100644 --- a/plugins/filter/parse_serial.py +++ b/plugins/filter/parse_serial.py @@ -50,9 +50,7 @@ from ansible_collections.community.crypto.plugins.module_utils.serial import ( def parse_serial_filter(input): if not isinstance(input, string_types): raise AnsibleFilterError( - "The input for the community.crypto.parse_serial filter must be a string; got {type} instead".format( - type=type(input) - ) + f"The input for the community.crypto.parse_serial filter must be a string; got {type(input)} instead" ) try: return parse_serial(to_native(input)) diff --git a/plugins/filter/split_pem.py b/plugins/filter/split_pem.py index 63c18b69..79d2d448 100644 --- a/plugins/filter/split_pem.py +++ b/plugins/filter/split_pem.py @@ -50,8 +50,7 @@ def split_pem_filter(data): """Split PEM file.""" if not isinstance(data, string_types): raise AnsibleFilterError( - "The community.crypto.split_pem input must be a text type, not %s" - % type(data) + f"The community.crypto.split_pem input must be a text type, not {type(data)}" ) data = to_text(data) diff --git a/plugins/filter/to_serial.py b/plugins/filter/to_serial.py index 6c0bc389..ec3d704c 100644 --- a/plugins/filter/to_serial.py +++ b/plugins/filter/to_serial.py @@ -48,9 +48,7 @@ from ansible_collections.community.crypto.plugins.module_utils.serial import to_ def to_serial_filter(input): if not isinstance(input, integer_types): raise AnsibleFilterError( - "The input for the community.crypto.to_serial filter must be an integer; got {type} instead".format( - type=type(input) - ) + f"The input for the community.crypto.to_serial filter must be an integer; got {type(input)} instead" ) if input < 0: raise AnsibleFilterError( diff --git a/plugins/filter/x509_certificate_info.py b/plugins/filter/x509_certificate_info.py index 8e85881f..1fda7ff9 100644 --- a/plugins/filter/x509_certificate_info.py +++ b/plugins/filter/x509_certificate_info.py @@ -326,19 +326,16 @@ def x509_certificate_info_filter(data, name_encoding="ignore"): """Extract information from X.509 PEM certificate.""" if not isinstance(data, string_types): raise AnsibleFilterError( - "The community.crypto.x509_certificate_info input must be a text type, not %s" - % type(data) + f"The community.crypto.x509_certificate_info input must be a text type, not {type(data)}" ) if not isinstance(name_encoding, string_types): raise AnsibleFilterError( - "The name_encoding option must be of a text type, not %s" - % type(name_encoding) + f"The name_encoding option must be of a text type, not {type(name_encoding)}" ) name_encoding = to_native(name_encoding) if name_encoding not in ("ignore", "idna", "unicode"): raise AnsibleFilterError( - 'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' - % name_encoding + f'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "{name_encoding}"' ) module = FilterModuleMock({"name_encoding": name_encoding}) diff --git a/plugins/filter/x509_crl_info.py b/plugins/filter/x509_crl_info.py index 15b53d11..5aa57342 100644 --- a/plugins/filter/x509_crl_info.py +++ b/plugins/filter/x509_crl_info.py @@ -177,24 +177,20 @@ def x509_crl_info_filter(data, name_encoding="ignore", list_revoked_certificates """Extract information from X.509 PEM certificate.""" if not isinstance(data, string_types): raise AnsibleFilterError( - "The community.crypto.x509_crl_info input must be a text type, not %s" - % type(data) + f"The community.crypto.x509_crl_info input must be a text type, not {type(data)}" ) if not isinstance(name_encoding, string_types): raise AnsibleFilterError( - "The name_encoding option must be of a text type, not %s" - % type(name_encoding) + f"The name_encoding option must be of a text type, not {type(name_encoding)}" ) if not isinstance(list_revoked_certificates, bool): raise AnsibleFilterError( - "The list_revoked_certificates option must be a boolean, not %s" - % type(list_revoked_certificates) + f"The list_revoked_certificates option must be a boolean, not {type(list_revoked_certificates)}" ) name_encoding = to_native(name_encoding) if name_encoding not in ("ignore", "idna", "unicode"): raise AnsibleFilterError( - 'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' - % name_encoding + f'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "{name_encoding}"' ) data = to_bytes(data) diff --git a/plugins/module_utils/acme/acme.py b/plugins/module_utils/acme/acme.py index a0f08e4c..d93ad984 100644 --- a/plugins/module_utils/acme/acme.py +++ b/plugins/module_utils/acme/acme.py @@ -66,7 +66,7 @@ def _decode_retry(module, response, info, retry_count): if retry_count >= RETRY_COUNT: raise ACMEProtocolException( module, - msg="Giving up after {retry} retries".format(retry=RETRY_COUNT), + msg=f"Giving up after {RETRY_COUNT} retries", info=info, response=response, ) @@ -77,8 +77,7 @@ def _decode_retry(module, response, info, retry_count): except (TypeError, ValueError): retry_after = 10 module.log( - "Retrieved a %s HTTP status on %s, retrying in %s seconds" - % (format_http_status(info["status"]), info["url"], retry_after) + f"Retrieved a {format_http_status(info['status'])} HTTP status on {info['url']}, retrying in {retry_after} seconds" ) time.sleep(retry_after) @@ -94,9 +93,7 @@ def _assert_fetch_url_success( allow_server_error=True, ): if info["status"] < 0: - raise NetworkException( - msg="Failure downloading %s, %s" % (info["url"], info["msg"]) - ) + raise NetworkException(msg=f"Failure downloading {info['url']}, {info['msg']}") if ( (300 <= info["status"] < 400 and not allow_redirect) @@ -169,16 +166,12 @@ class ACMEDirectory: continue if info["status"] not in (200, 204): raise NetworkException( - "Failed to get replay-nonce, got status {0}".format( - format_http_status(info["status"]) - ) + f"Failed to get replay-nonce, got status {format_http_status(info['status'])}" ) if "replay-nonce" in info: return info["replay-nonce"] self.module.log( - "HEAD to {0} did return status {1}, but no replay-nonce header!".format( - url, format_http_status(info["status"]) - ) + f"HEAD to {url} did return status {format_http_status(info['status'])}, but no replay-nonce header!" ) if retry_count >= 5: raise ACMEProtocolException( @@ -228,9 +221,7 @@ class ACMEClient: passphrase=self.account_key_passphrase, ) except KeyParsingError as e: - raise ModuleFailException( - "Error while parsing account key: {msg}".format(msg=e.msg) - ) + raise ModuleFailException(f"Error while parsing account key: {e.msg}") self.account_jwk = self.account_key_data["jwk"] self.account_jws_header = { "alg": self.account_key_data["alg"], @@ -276,7 +267,7 @@ class ACMEClient: protected64 = nopad_b64(self.module.jsonify(protected).encode("utf8")) except Exception as e: raise ModuleFailException( - "Failed to encode payload / headers as JSON: {0}".format(e) + f"Failed to encode payload / headers as JSON: {e}" ) return self.backend.sign(payload64, protected64, key_data) @@ -287,16 +278,13 @@ class ACMEClient: """ if self._debug: with open("acme.log", "ab") as f: - f.write( - "[{0}] {1}\n".format( - datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%s"), msg - ).encode("utf-8") - ) + timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%s") + f.write(f"[{timestamp}] {msg}\n".encode("utf-8")) if data is not None: f.write( - "{0}\n\n".format( - json.dumps(data, indent=2, sort_keys=True) - ).encode("utf-8") + f"{json.dumps(data, indent=2, sort_keys=True)}\n\n".encode( + "utf-8" + ) ) def send_signed_request( @@ -389,9 +377,7 @@ class ACMEClient: result = content except ValueError: raise NetworkException( - "Failed to parse the ACME response: {0} {1}".format( - url, content - ) + f"Failed to parse the ACME response: {url} {content}" ) else: result = content @@ -471,9 +457,7 @@ class ACMEClient: parsed_json_result = True except ValueError: raise NetworkException( - "Failed to parse the ACME response: {0} {1}".format( - uri, content - ) + f"Failed to parse the ACME response: {uri} {content}" ) else: result = content @@ -513,9 +497,7 @@ class ACMEClient: cert_filename=cert_filename, cert_content=cert_content, ) - url = "{base}/{cert_id}".format( - base=self.directory.directory["renewalInfo"].rstrip("/"), cert_id=cert_id - ) + url = f"{self.directory.directory['renewalInfo'].rstrip('/')}/{cert_id}" data, info = self.get_request( url, parse_json_result=True, fail_on_error=True, get_only=True @@ -593,31 +575,25 @@ def create_backend(module, needs_acme_v2=True): if CRYPTOGRAPHY_VERSION is None: msg = missing_required_lib("cryptography") else: - msg = "Unexpected error while preparing cryptography: {0}".format( - CRYPTOGRAPHY_ERROR.splitlines()[-1] - ) + msg = f"Unexpected error while preparing cryptography: {CRYPTOGRAPHY_ERROR.splitlines()[-1]}" module.fail_json(msg=msg, exception=CRYPTOGRAPHY_ERROR) if not HAS_CURRENT_CRYPTOGRAPHY: # We succeeded importing cryptography, but its version is too old. + mrl = missing_required_lib( + f"cryptography >= {CRYPTOGRAPHY_MINIMAL_VERSION}" + ) module.fail_json( - msg="Found cryptography, but only version {0}. {1}".format( - CRYPTOGRAPHY_VERSION, - missing_required_lib( - "cryptography >= {0}".format(CRYPTOGRAPHY_MINIMAL_VERSION) - ), - ) + msg=f"Found cryptography, but only version {CRYPTOGRAPHY_VERSION}. {mrl}" ) module.debug( - "Using cryptography backend (library version {0})".format( - CRYPTOGRAPHY_VERSION - ) + f"Using cryptography backend (library version {CRYPTOGRAPHY_VERSION})" ) module_backend = CryptographyBackend(module) elif backend == "openssl": module.debug("Using OpenSSL binary backend") module_backend = OpenSSLCLIBackend(module) else: - module.fail_json(msg='Unknown crypto backend "{0}"!'.format(backend)) + module.fail_json(msg=f'Unknown crypto backend "{backend}"!') # Check common module parameters if not module.params["validate_certs"]: diff --git a/plugins/module_utils/acme/backend_cryptography.py b/plugins/module_utils/acme/backend_cryptography.py index 51a5c5cf..1a6f0474 100644 --- a/plugins/module_utils/acme/backend_cryptography.py +++ b/plugins/module_utils/acme/backend_cryptography.py @@ -91,14 +91,12 @@ class CryptographyChainMatcher(ChainMatcher): except Exception: if criterium_idx is None: module.warn( - "Criterium has invalid {0} value. Ignoring criterium.".format( - name - ) + f"Criterium has invalid {name} value. Ignoring criterium." ) else: module.warn( - "Criterium {0} in select_chain has invalid {1} value. " - "Ignoring criterium.".format(criterium_idx, name) + f"Criterium {criterium_idx} in select_chain has invalid {name} value. " + "Ignoring criterium." ) return None @@ -181,9 +179,7 @@ class CryptographyChainMatcher(ChainMatcher): if matches: return True except Exception as e: - self.module.warn( - "Error while loading certificate {0}: {1}".format(cert, e) - ) + self.module.warn(f"Error while loading certificate {cert}: {e}") return False @@ -211,7 +207,7 @@ class CryptographyBackend(CryptoBackend): backend=_cryptography_backend, ) except Exception as e: - raise KeyParsingError("error while loading key: {0}".format(e)) + raise KeyParsingError(f"error while loading key: {e}") if isinstance(key, cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey): pk = key.public_key().public_numbers() return { @@ -250,9 +246,7 @@ class CryptographyBackend(CryptoBackend): point_size = 66 curve = "P-521" else: - raise KeyParsingError( - "unknown elliptic curve: {0}".format(pk.curve.name) - ) + raise KeyParsingError(f"unknown elliptic curve: {pk.curve.name}") num_bytes = (bits + 7) // 8 return { "key_obj": key, @@ -268,10 +262,10 @@ class CryptographyBackend(CryptoBackend): "point_size": point_size, } else: - raise KeyParsingError('unknown key type "{0}"'.format(type(key))) + raise KeyParsingError(f'unknown key type "{type(key)}"') def sign(self, payload64, protected64, key_data): - sign_payload = "{0}.{1}".format(protected64, payload64).encode("utf8") + sign_payload = f"{protected64}.{payload64}".encode("utf8") if "mac_obj" in key_data: mac = key_data["mac_obj"]() mac.update(sign_payload) @@ -320,16 +314,12 @@ class CryptographyBackend(CryptoBackend): hashbytes = 64 else: raise BackendException( - "Unsupported MAC key algorithm for cryptography backend: {0}".format( - alg - ) + f"Unsupported MAC key algorithm for cryptography backend: {alg}" ) key_bytes = base64.urlsafe_b64decode(key) if len(key_bytes) < hashbytes: raise BackendException( - "{0} key must be at least {1} bytes long (after Base64 decoding)".format( - alg, hashbytes - ) + f"{alg} key must be at least {hashbytes} bytes long (after Base64 decoding)" ) return { "mac_obj": lambda: cryptography.hazmat.primitives.hmac.HMAC( @@ -382,7 +372,7 @@ class CryptographyBackend(CryptoBackend): add_identifier(("ip", name.value.compressed)) else: raise BackendException( - "Found unsupported SAN identifier {0}".format(name) + f"Found unsupported SAN identifier {name}" ) return result @@ -425,10 +415,8 @@ class CryptographyBackend(CryptoBackend): ) except Exception as e: if cert_filename is None: - raise BackendException("Cannot parse certificate: {0}".format(e)) - raise BackendException( - "Cannot parse certificate {0}: {1}".format(cert_filename, e) - ) + raise BackendException(f"Cannot parse certificate: {e}") + raise BackendException(f"Cannot parse certificate {cert_filename}: {e}") if now is None: now = self.get_now() @@ -460,10 +448,8 @@ class CryptographyBackend(CryptoBackend): ) except Exception as e: if cert_filename is None: - raise BackendException("Cannot parse certificate: {0}".format(e)) - raise BackendException( - "Cannot parse certificate {0}: {1}".format(cert_filename, e) - ) + raise BackendException(f"Cannot parse certificate: {e}") + raise BackendException(f"Cannot parse certificate {cert_filename}: {e}") ski = None try: diff --git a/plugins/module_utils/acme/backend_openssl_cli.py b/plugins/module_utils/acme/backend_openssl_cli.py index 73dc3228..b225da96 100644 --- a/plugins/module_utils/acme/backend_openssl_cli.py +++ b/plugins/module_utils/acme/backend_openssl_cli.py @@ -44,7 +44,7 @@ _OPENSSL_ENVIRONMENT_UPDATE = dict(LANG="C", LC_ALL="C", LC_MESSAGES="C", LC_CTY def _extract_date(out_text, name, cert_filename_suffix=""): try: - date_str = re.search(r"\s+%s\s*:\s+(.*)" % name, out_text).group(1) + date_str = re.search(rf"\s+{name}\s*:\s+(.*)", out_text).group(1) # For some reason Python's strptime() does not return any timezone information, # even though the information is there and a supported timezone for all supported # Python implementations (GMT). So we have to modify the datetime object by @@ -53,12 +53,10 @@ def _extract_date(out_text, name, cert_filename_suffix=""): datetime.datetime.strptime(date_str, "%b %d %H:%M:%S %Y %Z") ) except AttributeError: - raise BackendException( - "No '{0}' date found{1}".format(name, cert_filename_suffix) - ) + raise BackendException(f"No '{name}' date found{cert_filename_suffix}") except ValueError as exc: raise BackendException( - "Failed to parse '{0}' date{1}: {2}".format(name, cert_filename_suffix, exc) + f"Failed to parse '{name}' date{cert_filename_suffix}: {exc}" ) @@ -67,20 +65,18 @@ def _decode_octets(octets_text): def _extract_octets(out_text, name, required=True, potential_prefixes=None): - regexp = r"\s+%s:\s*\n\s+%s([A-Fa-f0-9]{2}(?::[A-Fa-f0-9]{2})*)\s*\n" % ( - name, - ( - ("(?:%s)" % "|".join(re.escape(pp) for pp in potential_prefixes)) - if potential_prefixes - else "" - ), + part = ( + f"(?:{'|'.join(re.escape(pp) for pp in potential_prefixes)})" + if potential_prefixes + else "" ) + regexp = rf"\s+{name}:\s*\n\s+{part}([A-Fa-f0-9]{{2}}(?::[A-Fa-f0-9]{{2}})*)\s*\n" match = re.search(regexp, out_text, re.MULTILINE | re.DOTALL) if match is not None: return _decode_octets(match.group(1)) if not required: return None - raise BackendException("No '{0}' octet string found".format(name)) + raise BackendException(f"No '{name}' octet string found") class OpenSSLCLIBackend(CryptoBackend): @@ -111,7 +107,7 @@ class OpenSSLCLIBackend(CryptoBackend): except Exception: pass raise KeyParsingError( - "failed to create temporary content file: %s" % to_native(err), + f"failed to create temporary content file: {err}", exception=traceback.format_exc(), ) f.close() @@ -132,7 +128,7 @@ class OpenSSLCLIBackend(CryptoBackend): # FIXME: add some kind of auto-detection account_key_type = "rsa" if account_key_type not in ("rsa", "ec"): - raise KeyParsingError('unknown key type "%s"' % account_key_type) + raise KeyParsingError(f'unknown key type "{account_key_type}"') openssl_keydump_cmd = [ self.openssl_binary, @@ -149,9 +145,7 @@ class OpenSSLCLIBackend(CryptoBackend): ) if rc != 0: raise BackendException( - "Error while running {cmd}: {stderr}".format( - cmd=" ".join(openssl_keydump_cmd), stderr=to_text(err) - ) + f"Error while running {' '.join(openssl_keydump_cmd)}: {to_text(err)}" ) out_text = to_text(out, errors="surrogate_or_strict") @@ -166,9 +160,9 @@ class OpenSSLCLIBackend(CryptoBackend): pub_exp = re.search( r"\npublicExponent: ([0-9]+)", out_text, re.MULTILINE | re.DOTALL ).group(1) - pub_exp = "{0:x}".format(int(pub_exp)) + pub_exp = f"{int(pub_exp):x}" if len(pub_exp) % 2: - pub_exp = "0{0}".format(pub_exp) + pub_exp = f"0{pub_exp}" return { "key_file": key_file, @@ -214,12 +208,12 @@ class OpenSSLCLIBackend(CryptoBackend): curve = "P-521" else: raise KeyParsingError( - "unknown elliptic curve: %s / %s" % (asn1_oid_curve, nist_curve) + f"unknown elliptic curve: {asn1_oid_curve} / {nist_curve}" ) num_bytes = (bits + 7) // 8 if len(pub_hex) != 2 * num_bytes: raise KeyParsingError( - "bad elliptic curve point (%s / %s)" % (asn1_oid_curve, nist_curve) + f"bad elliptic curve point ({asn1_oid_curve} / {nist_curve})" ) return { "key_file": key_file, @@ -236,7 +230,7 @@ class OpenSSLCLIBackend(CryptoBackend): } def sign(self, payload64, protected64, key_data): - sign_payload = "{0}.{1}".format(protected64, payload64).encode("utf8") + sign_payload = f"{protected64}.{payload64}".encode("utf8") if key_data["type"] == "hmac": hex_key = to_native( binascii.hexlify(base64.urlsafe_b64decode(key_data["jwk"]["k"])) @@ -245,7 +239,7 @@ class OpenSSLCLIBackend(CryptoBackend): "-mac", "hmac", "-macopt", - "hexkey:{0}".format(hex_key), + f"hexkey:{hex_key}", "-binary", ] else: @@ -253,7 +247,7 @@ class OpenSSLCLIBackend(CryptoBackend): openssl_sign_cmd = [ self.openssl_binary, "dgst", - "-{0}".format(key_data["hash"]), + f"-{key_data['hash']}", ] + cmd_postfix rc, out, err = self.module.run_command( @@ -265,9 +259,7 @@ class OpenSSLCLIBackend(CryptoBackend): ) if rc != 0: raise BackendException( - "Error while running {cmd}: {stderr}".format( - cmd=" ".join(openssl_sign_cmd), stderr=to_text(err) - ) + f"Error while running {' '.join(openssl_sign_cmd)}: {to_text(err)}" ) if key_data["type"] == "ec": @@ -279,14 +271,13 @@ class OpenSSLCLIBackend(CryptoBackend): ) expected_len = 2 * key_data["point_size"] sig = re.findall( - r"prim:\s+INTEGER\s+:([0-9A-F]{1,%s})\n" % expected_len, + rf"prim:\s+INTEGER\s+:([0-9A-F]{{1,{expected_len}}})\n", to_text(der_out, errors="surrogate_or_strict"), ) if len(sig) != 2: + der_output = to_text(der_out, errors="surrogate_or_strict") raise BackendException( - "failed to generate Elliptic Curve signature; cannot parse DER output: {0}".format( - to_text(der_out, errors="surrogate_or_strict") - ) + f"failed to generate Elliptic Curve signature; cannot parse DER output: {der_output}" ) sig[0] = (expected_len - len(sig[0])) * "0" + sig[0] sig[1] = (expected_len - len(sig[1])) * "0" + sig[1] @@ -311,14 +302,12 @@ class OpenSSLCLIBackend(CryptoBackend): hashbytes = 64 else: raise BackendException( - "Unsupported MAC key algorithm for OpenSSL backend: {0}".format(alg) + f"Unsupported MAC key algorithm for OpenSSL backend: {alg}" ) key_bytes = base64.urlsafe_b64decode(key) if len(key_bytes) < hashbytes: raise BackendException( - "{0} key must be at least {1} bytes long (after Base64 decoding)".format( - alg, hashbytes - ) + f"{alg} key must be at least {hashbytes} bytes long (after Base64 decoding)" ) return { "type": "hmac", @@ -370,9 +359,7 @@ class OpenSSLCLIBackend(CryptoBackend): ) if rc != 0: raise BackendException( - "Error while running {cmd}: {stderr}".format( - cmd=" ".join(openssl_csr_cmd), stderr=to_text(err) - ) + f"Error while running {' '.join(openssl_csr_cmd)}: {to_text(err)}" ) identifiers = set() @@ -404,9 +391,7 @@ class OpenSSLCLIBackend(CryptoBackend): elif san.lower().startswith("ip address:"): add_identifier(("ip", self._normalize_ip(san[11:]))) else: - raise BackendException( - 'Found unsupported SAN identifier "{0}"'.format(san) - ) + raise BackendException(f'Found unsupported SAN identifier "{san}"') return result def get_csr_identifiers(self, csr_filename=None, csr_content=None): @@ -438,7 +423,7 @@ class OpenSSLCLIBackend(CryptoBackend): elif cert_filename is not None: if not os.path.exists(cert_filename): return -1 - cert_filename_suffix = " in {0}".format(cert_filename) + cert_filename_suffix = f" in {cert_filename}" else: return -1 @@ -459,9 +444,7 @@ class OpenSSLCLIBackend(CryptoBackend): ) if rc != 0: raise BackendException( - "Error while running {cmd}: {stderr}".format( - cmd=" ".join(openssl_cert_cmd), stderr=to_text(err) - ) + f"Error while running {' '.join(openssl_cert_cmd)}: {to_text(err)}" ) out_text = to_text(out, errors="surrogate_or_strict") @@ -489,7 +472,7 @@ class OpenSSLCLIBackend(CryptoBackend): filename = cert_filename data = None if cert_filename is not None: - cert_filename_suffix = " in {0}".format(cert_filename) + cert_filename_suffix = f" in {cert_filename}" else: filename = "/dev/stdin" data = to_bytes(cert_content) @@ -512,9 +495,7 @@ class OpenSSLCLIBackend(CryptoBackend): ) if rc != 0: raise BackendException( - "Error while running {cmd}: {stderr}".format( - cmd=" ".join(openssl_cert_cmd), stderr=to_text(err) - ) + f"Error while running {' '.join(openssl_cert_cmd)}: {to_text(err)}" ) out_text = to_text(out, errors="surrogate_or_strict") diff --git a/plugins/module_utils/acme/backends.py b/plugins/module_utils/acme/backends.py index 2b98ed3d..3127eb11 100644 --- a/plugins/module_utils/acme/backends.py +++ b/plugins/module_utils/acme/backends.py @@ -53,15 +53,13 @@ def _reduce_fractional_digits(timestamp_str): # RFC 3339 (https://www.rfc-editor.org/info/rfc3339) m = _FRACTIONAL_MATCHER.match(timestamp_str) if not m: - raise BackendException( - "Cannot parse ISO 8601 timestamp {0!r}".format(timestamp_str) - ) + raise BackendException(f"Cannot parse ISO 8601 timestamp {timestamp_str!r}") timestamp, fractional, timezone = m.groups() if len(fractional) > 7: # Python does not support anything smaller than microseconds # (Golang supports nanoseconds, Boulder often emits more fractional digits, which Python chokes on) fractional = fractional[:7] - return "%s%s%s" % (timestamp, fractional, timezone) + return f"{timestamp}{fractional}{timezone}" def _parse_acme_timestamp(timestamp_str, with_timezone): @@ -87,9 +85,7 @@ def _parse_acme_timestamp(timestamp_str, with_timezone): if with_timezone else remove_timezone(result) ) - raise BackendException( - "Cannot parse ISO 8601 timestamp {0!r}".format(timestamp_str) - ) + raise BackendException(f"Cannot parse ISO 8601 timestamp {timestamp_str!r}") @six.add_metaclass(abc.ABCMeta) diff --git a/plugins/module_utils/acme/certificate.py b/plugins/module_utils/acme/certificate.py index 0ed1993d..894b53b6 100644 --- a/plugins/module_utils/acme/certificate.py +++ b/plugins/module_utils/acme/certificate.py @@ -62,7 +62,7 @@ class ACMECertificateClient: raise ModuleFailException(msg="Account does not exist or is deactivated.") if self.csr is not None and not os.path.exists(self.csr): - raise ModuleFailException("CSR %s not found" % (self.csr)) + raise ModuleFailException(f"CSR {self.csr} not found") # Extract list of identifiers from CSR if self.csr is not None or self.csr_content is not None: @@ -84,9 +84,7 @@ class ACMECertificateClient: ) except ValueError as exc: self.module.warn( - "Error while parsing criterium: {error}. Ignoring criterium.".format( - error=exc - ) + f"Error while parsing criterium: {exc}. Ignoring criterium." ) return select_chain_matcher @@ -154,17 +152,13 @@ class ACMECertificateClient: for authz in order.authorizations.values(): if authz.status not in ("valid", "pending"): bad_authzs.append( - "{authz} (status={status!r})".format( - authz=authz.combined_identifier, - status=authz.status, - ) + f"{authz.combined_identifier} (status={authz.status!r})" ) if bad_authzs: + bad_authzs = ", ".join(sorted(bad_authzs)) raise ModuleFailException( "Some of the authorizations for the order are in a bad state, so the order" - " can no longer be satisfied: {bad_authzs}".format( - bad_authzs=", ".join(sorted(bad_authzs)), - ), + f" can no longer be satisfied: {bad_authzs}", ) def collect_invalid_authzs(self, order): @@ -201,18 +195,14 @@ class ACMECertificateClient: alt_cert = CertificateChain.download(self.client, alternate) except ModuleFailException as e: self.module.warn( - "Error while downloading alternative certificate {0}: {1}".format( - alternate, e - ) + f"Error while downloading alternative certificate {alternate}: {e}" ) continue if alt_cert.cert is not None: alternate_chains.append(alt_cert) else: self.module.warn( - "Error while downloading alternative certificate {0}: no certificate found".format( - alternate - ) + f"Error while downloading alternative certificate {alternate}: no certificate found" ) return alternate_chains @@ -222,22 +212,18 @@ class ACMECertificateClient: """ if order.status != "valid": raise ModuleFailException( - "The order must be valid, but has state {state!r}!".format( - state=order.state - ) + f"The order must be valid, but has state {order.state!r}!" ) if not order.certificate_uri: raise ModuleFailException( - "Order's crtificate URL {url!r} is empty!".format( - url=order.certificate_uri - ) + f"Order's crtificate URL {order.certificate_uri!r} is empty!" ) cert = CertificateChain.download(self.client, order.certificate_uri) if cert.cert is None: raise ModuleFailException( - "Certificate at {url} is empty!".format(url=order.certificate_uri) + f"Certificate at {order.certificate_uri} is empty!" ) alternate_chains = None @@ -256,7 +242,7 @@ class ACMECertificateClient: for identifier, authz in order.authorizations.items(): if authz.status != "valid": authz.raise_error( - 'Status is {status!r} and not "valid"'.format(status=authz.status), + f'Status is {authz.status!r} and not "valid"', module=self.module, ) @@ -269,7 +255,7 @@ class ACMECertificateClient: for chain in chains: if matcher.match(chain): self.module.debug( - "Found matching chain for criterium {0}".format(criterium_idx) + f"Found matching chain for criterium {criterium_idx}" ) return chain return None @@ -312,9 +298,7 @@ class ACMECertificateClient: pass if authz is None or authz.status != "deactivated": self.module.warn( - warning="Could not deactivate authz object {0}.".format( - authz_uri - ) + warning=f"Could not deactivate authz object {authz_uri}." ) else: for authz in order.authorizations.values(): @@ -325,7 +309,5 @@ class ACMECertificateClient: pass if authz.status != "deactivated": self.module.warn( - warning="Could not deactivate authz object {0}.".format( - authz.url - ) + warning=f"Could not deactivate authz object {authz.url}." ) diff --git a/plugins/module_utils/acme/certificates.py b/plugins/module_utils/acme/certificates.py index fea162ec..a280a314 100644 --- a/plugins/module_utils/acme/certificates.py +++ b/plugins/module_utils/acme/certificates.py @@ -44,9 +44,7 @@ class CertificateChain: "application/pem-certificate-chain" ): raise ModuleFailException( - "Cannot download certificate chain from {0}, as content type is not application/pem-certificate-chain: {1} (headers: {2})".format( - url, content, info - ) + f"Cannot download certificate chain from {url}, as content type is not application/pem-certificate-chain: {content} (headers: {info})" ) result = cls(url) @@ -63,9 +61,7 @@ class CertificateChain: if result.cert is None: raise ModuleFailException( - "Failed to parse certificate chain download from {0}: {1} (headers: {2})".format( - url, content, info - ) + f"Failed to parse certificate chain download from {url}: {content} (headers: {info})" ) return result diff --git a/plugins/module_utils/acme/challenges.py b/plugins/module_utils/acme/challenges.py index d18aa59e..c1fcc43c 100644 --- a/plugins/module_utils/acme/challenges.py +++ b/plugins/module_utils/acme/challenges.py @@ -37,11 +37,11 @@ def create_key_authorization(client, token): client.account_jwk, sort_keys=True, separators=(",", ":") ) thumbprint = nopad_b64(hashlib.sha256(accountkey_json.encode("utf8")).digest()) - return "{0}.{1}".format(token, thumbprint) + return f"{token}.{thumbprint}" def combine_identifier(identifier_type, identifier): - return "{type}:{identifier}".format(type=identifier_type, identifier=identifier) + return f"{identifier_type}:{identifier}" def normalize_combined_identifier(identifier): @@ -55,9 +55,7 @@ def split_identifier(identifier): parts = identifier.split(":", 1) if len(parts) != 2: raise ModuleFailException( - 'Identifier "{identifier}" is not of the form :'.format( - identifier=identifier - ) + f'Identifier "{identifier}" is not of the form :' ) return parts @@ -94,7 +92,7 @@ class Challenge: if self.type == "http-01": # https://tools.ietf.org/html/rfc8555#section-8.3 return { - "resource": ".well-known/acme-challenge/{token}".format(token=token), + "resource": f".well-known/acme-challenge/{token}", "resource_value": key_authorization, } @@ -104,9 +102,7 @@ class Challenge: # https://tools.ietf.org/html/rfc8555#section-8.4 resource = "_acme-challenge" value = nopad_b64(hashlib.sha256(to_bytes(key_authorization)).digest()) - record = "{0}.{1}".format( - resource, identifier[2:] if identifier.startswith("*.") else identifier - ) + record = f"{resource}.{identifier[2:] if identifier.startswith('*.') else identifier}" return { "resource": resource, "resource_value": value, @@ -152,7 +148,7 @@ class Authorization: self.identifier = data["identifier"]["value"] self.identifier_type = data["identifier"]["type"] if data.get("wildcard", False): - self.identifier = "*.{0}".format(self.identifier) + self.identifier = f"*.{self.identifier}" def __init__(self, url): self.url = url @@ -238,23 +234,17 @@ class Authorization: # details for all of them before failing for challenge in self.challenges: if challenge.status == "invalid": - msg = "Challenge {type}".format(type=challenge.type) + msg = f"Challenge {challenge.type}" if "error" in challenge.data: - msg = "{msg}: {problem}".format( - msg=msg, - problem=format_error_problem( - challenge.data["error"], - subproblem_prefix="{0}.".format(challenge.type), - ), + problem = format_error_problem( + challenge.data["error"], + subproblem_prefix=f"{challenge.type}.", ) + msg = f"{msg}: {problem}" error_details.append(msg) raise ACMEProtocolException( module, - "Failed to validate challenge for {identifier}: {error}. {details}".format( - identifier=self.combined_identifier, - error=error_msg, - details="; ".join(error_details), - ), + f"Failed to validate challenge for {self.combined_identifier}: {error_msg}. {'; '.join(error_details)}", extras=dict( identifier=self.combined_identifier, authorization=self.data, @@ -287,10 +277,7 @@ class Authorization: challenge = self.find_challenge(challenge_type) if challenge is None: raise ModuleFailException( - 'Found no challenge of type "{challenge}" for identifier {identifier}!'.format( - challenge=challenge_type, - identifier=self.combined_identifier, - ) + f'Found no challenge of type "{challenge_type}" for identifier {self.combined_identifier}!' ) challenge.call_validate(client) diff --git a/plugins/module_utils/acme/errors.py b/plugins/module_utils/acme/errors.py index f1118772..61a59efa 100644 --- a/plugins/module_utils/acme/errors.py +++ b/plugins/module_utils/acme/errors.py @@ -14,7 +14,7 @@ def format_http_status(status_code): expl = http_responses.get(status_code) if not expl: return str(status_code) - return "%d %s" % (status_code, expl) + return f"{status_code} {expl}" def format_error_problem(problem, subproblem_prefix=""): @@ -22,26 +22,18 @@ def format_error_problem(problem, subproblem_prefix=""): "type", "about:blank" ) # https://www.rfc-editor.org/rfc/rfc7807#section-3.1 if "title" in problem: - msg = 'Error "{title}" ({type})'.format( - type=error_type, - title=problem["title"], - ) + msg = f'Error "{problem["title"]}" ({error_type})' else: - msg = "Error {type}".format(type=error_type) + msg = f"Error {error_type}" if "detail" in problem: - msg += ': "{detail}"'.format(detail=problem["detail"]) + msg += f': "{problem["detail"]}"' subproblems = problem.get("subproblems") if subproblems is not None: - msg = "{msg} Subproblems:".format(msg=msg) + msg = f"{msg} Subproblems:" for index, problem in enumerate(subproblems): - index_str = "{prefix}{index}".format(prefix=subproblem_prefix, index=index) - msg = "{msg}\n({index}) {problem}".format( - msg=msg, - index=index_str, - problem=format_error_problem( - problem, subproblem_prefix="{0}.".format(index_str) - ), - ) + index_str = f"{subproblem_prefix}{index}" + problem = format_error_problem(problem, subproblem_prefix=f"{index_str}.") + msg = f"{msg}\n({index_str}) {problem}" return msg @@ -116,55 +108,37 @@ class ACMEProtocolException(ModuleFailException): ): error_type = content_json["type"] if "status" in content_json and content_json["status"] != code: - code_msg = ( - "status {problem_code} (HTTP status: {http_code})".format( - http_code=format_http_status(code), - problem_code=content_json["status"], - ) - ) + code_msg = f"status {content_json['status']} (HTTP status: {format_http_status(code)})" else: - code_msg = "status {problem_code}".format( - problem_code=format_http_status(code) - ) + code_msg = f"status {format_http_status(code)}" if code == -1 and info.get("msg"): - code_msg = "error: {msg}".format(msg=info["msg"]) + code_msg = f"error: {info['msg']}" subproblems = content_json.pop("subproblems", None) - add_msg = " {problem}.".format( - problem=format_error_problem(content_json) - ) + add_msg = f" {format_error_problem(content_json)}." extras["problem"] = content_json extras["subproblems"] = subproblems or [] if subproblems is not None: - add_msg = "{add_msg} Subproblems:".format(add_msg=add_msg) + add_msg = f"{add_msg} Subproblems:" for index, problem in enumerate(subproblems): - add_msg = "{add_msg}\n({index}) {problem}.".format( - add_msg=add_msg, - index=index, - problem=format_error_problem( - problem, subproblem_prefix="{0}.".format(index) - ), + problem = format_error_problem( + problem, subproblem_prefix=f"{index}." ) + add_msg = f"{add_msg}\n({index}) {problem}." else: - code_msg = "HTTP status {code}".format(code=format_http_status(code)) + code_msg = f"HTTP status {format_http_status(code)}" if code == -1 and info.get("msg"): - code_msg = "error: {msg}".format(msg=info["msg"]) + code_msg = f"error: {info['msg']}" if content_json is not None: - add_msg = " The JSON error result: {content}".format( - content=content_json - ) + add_msg = f" The JSON error result: {content_json}" elif content is not None: - add_msg = " The raw error result: {content}".format( - content=to_text(content) - ) - msg = "{msg} for {url} with {code}".format(msg=msg, url=url, code=code_msg) + add_msg = f" The raw error result: {to_text(content)}" + msg = f"{msg} for {url} with {code_msg}" elif content_json is not None: - add_msg = " The JSON result: {content}".format(content=content_json) + add_msg = f" The JSON result: {content_json}" elif content is not None: - add_msg = " The raw result: {content}".format(content=to_text(content)) + add_msg = f" The raw result: {to_text(content)}" - super(ACMEProtocolException, self).__init__( - "{msg}.{add_msg}".format(msg=msg, add_msg=add_msg), **extras - ) + super(ACMEProtocolException, self).__init__(f"{msg}.{add_msg}", **extras) self.problem = {} self.subproblems = [] self.error_code = error_code diff --git a/plugins/module_utils/acme/io.py b/plugins/module_utils/acme/io.py index 4f6f6681..d2fb7fb2 100644 --- a/plugins/module_utils/acme/io.py +++ b/plugins/module_utils/acme/io.py @@ -22,7 +22,7 @@ def read_file(fn, mode="b"): with open(fn, "r" + mode) as f: return f.read() except Exception as e: - raise ModuleFailException('Error while reading file "{0}": {1}'.format(fn, e)) + raise ModuleFailException(f'Error while reading file "{fn}": {e}') # This function was adapted from an earlier version of https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/uri.py @@ -44,7 +44,7 @@ def write_file(module, dest, content): pass os.remove(tmpsrc) raise ModuleFailException( - "failed to create temporary content file: %s" % to_native(err), + f"failed to create temporary content file: {err}", exception=traceback.format_exc(), ) f.close() @@ -56,26 +56,26 @@ def write_file(module, dest, content): os.remove(tmpsrc) except Exception: pass - raise ModuleFailException("Source %s does not exist" % (tmpsrc)) + raise ModuleFailException(f"Source {tmpsrc} does not exist") if not os.access(tmpsrc, os.R_OK): os.remove(tmpsrc) - raise ModuleFailException("Source %s not readable" % (tmpsrc)) + raise ModuleFailException(f"Source {tmpsrc} not readable") checksum_src = module.sha1(tmpsrc) # check if there is no dest file if os.path.exists(dest): # raise an error if copy has no permission on dest if not os.access(dest, os.W_OK): os.remove(tmpsrc) - raise ModuleFailException("Destination %s not writable" % (dest)) + raise ModuleFailException(f"Destination {dest} not writable") if not os.access(dest, os.R_OK): os.remove(tmpsrc) - raise ModuleFailException("Destination %s not readable" % (dest)) + raise ModuleFailException(f"Destination {dest} not readable") checksum_dest = module.sha1(dest) else: dirname = os.path.dirname(dest) or "." if not os.access(dirname, os.W_OK): os.remove(tmpsrc) - raise ModuleFailException("Destination dir %s not writable" % (dirname)) + raise ModuleFailException(f"Destination dir {dirname} not writable") if checksum_src != checksum_dest: try: shutil.copyfile(tmpsrc, dest) @@ -83,7 +83,7 @@ def write_file(module, dest, content): except Exception as err: os.remove(tmpsrc) raise ModuleFailException( - "failed to copy %s to %s: %s" % (tmpsrc, dest, to_native(err)), + f"failed to copy {tmpsrc} to {dest}: {to_native(err)}", exception=traceback.format_exc(), ) os.remove(tmpsrc) diff --git a/plugins/module_utils/acme/orders.py b/plugins/module_utils/acme/orders.py index 5b0d47f0..6f21170c 100644 --- a/plugins/module_utils/acme/orders.py +++ b/plugins/module_utils/acme/orders.py @@ -133,11 +133,7 @@ class Order: ): if message_callback: message_callback( - "Stop passing `replaces={replaces}` due to error {code} {type} when creating ACME order".format( - code=exc.error_code, - type=exc.error_type, - replaces=replaces_cert_id, - ) + f"Stop passing `replaces={replaces_cert_id}` due to error {exc.error_code} {exc.error_type} when creating ACME order" ) replaces_cert_id = None continue @@ -167,9 +163,7 @@ class Order: if self.status != "valid": raise ACMEProtocolException( client.module, - 'Failed to wait for order to complete; got status "{status}"'.format( - status=self.status - ), + f'Failed to wait for order to complete; got status "{self.status}"', content_json=self.data, ) @@ -198,9 +192,7 @@ class Order: if self.status not in ["procesing", "valid", "invalid"]: raise ACMEProtocolException( client.module, - 'Failed to finalize order; got status "{status}"'.format( - status=self.status - ), + f'Failed to finalize order; got status "{self.status}"', info=info, content_json=result, ) diff --git a/plugins/module_utils/acme/utils.py b/plugins/module_utils/acme/utils.py index 7321dcef..d5881fdd 100644 --- a/plugins/module_utils/acme/utils.py +++ b/plugins/module_utils/acme/utils.py @@ -32,9 +32,8 @@ def der_to_pem(der_cert): """ Convert the DER format certificate in der_cert to a PEM format certificate and return it. """ - return """-----BEGIN CERTIFICATE-----\n{0}\n-----END CERTIFICATE-----\n""".format( - "\n".join(textwrap.wrap(base64.b64encode(der_cert).decode("utf8"), 64)) - ) + content = "\n".join(textwrap.wrap(base64.b64encode(der_cert).decode("utf8"), 64)) + return f"-----BEGIN CERTIFICATE-----\n{content}\n-----END CERTIFICATE-----\n" def pem_to_der(pem_filename=None, pem_content=None): @@ -52,7 +51,7 @@ def pem_to_der(pem_filename=None, pem_content=None): lines = list(f) except Exception as err: raise ModuleFailException( - "cannot load PEM file {0}: {1}".format(pem_filename, to_native(err)), + f"cannot load PEM file {pem_filename}: {to_native(err)}", exception=traceback.format_exc(), ) else: @@ -104,7 +103,7 @@ def parse_retry_after(value, relative_with_timezone=True, now=None): except ValueError: pass - raise ValueError("Cannot parse Retry-After header value %s" % repr(value)) + raise ValueError(f"Cannot parse Retry-After header value {repr(value)}") def compute_cert_id( @@ -138,4 +137,4 @@ def compute_cert_id( serial = to_native(base64.urlsafe_b64encode(serial_bytes)).replace("=", "") # Compose cert ID - return "{aki}.{serial}".format(aki=aki, serial=serial) + return f"{aki}.{serial}" diff --git a/plugins/module_utils/crypto/_asn1.py b/plugins/module_utils/crypto/_asn1.py index 17479b4f..c0478992 100644 --- a/plugins/module_utils/crypto/_asn1.py +++ b/plugins/module_utils/crypto/_asn1.py @@ -82,8 +82,7 @@ def serialize_asn1_string_as_der(value): if value_type != "UTF8": raise ValueError( - 'The ASN.1 serialized string is not a known type "{0}", only UTF8 types are ' - "supported".format(value_type) + f'The ASN.1 serialized string is not a known type "{value_type}", only UTF8 types are supported' ) b_value = to_bytes(asn1_value, encoding="utf-8", errors="surrogate_or_strict") @@ -117,7 +116,7 @@ def pack_asn1(tag_class, constructed, tag_number, b_data): b_asn1_data = bytearray() if tag_class < 0 or tag_class > 3: - raise ValueError("tag_class must be between 0 and 3 not %s" % tag_class) + raise ValueError(f"tag_class must be between 0 and 3 not {tag_class}") # Bit 8 and 7 denotes the class. identifier_octets = tag_class << 6 diff --git a/plugins/module_utils/crypto/_objects.py b/plugins/module_utils/crypto/_objects.py index 22b2c642..957ec186 100644 --- a/plugins/module_utils/crypto/_objects.py +++ b/plugins/module_utils/crypto/_objects.py @@ -15,9 +15,7 @@ for dotted, names in OID_MAP.items(): for name in names: if name in NORMALIZE_NAMES and OID_LOOKUP[name] != dotted: raise AssertionError( - 'Name collision during setup: "{0}" for OIDs {1} and {2}'.format( - name, dotted, OID_LOOKUP[name] - ) + f'Name collision during setup: "{name}" for OIDs {dotted} and {OID_LOOKUP[name]}' ) NORMALIZE_NAMES[name] = names[0] NORMALIZE_NAMES_SHORT[name] = names[-1] @@ -25,9 +23,7 @@ for dotted, names in OID_MAP.items(): for alias, original in [("userID", "userId")]: if alias in NORMALIZE_NAMES: raise AssertionError( - 'Name collision during adding aliases: "{0}" (alias for "{1}") is already mapped to OID {2}'.format( - alias, original, OID_LOOKUP[alias] - ) + f'Name collision during adding aliases: "{alias}" (alias for "{original}") is already mapped to OID {OID_LOOKUP[alias]}' ) NORMALIZE_NAMES[alias] = original NORMALIZE_NAMES_SHORT[alias] = NORMALIZE_NAMES_SHORT[original] diff --git a/plugins/module_utils/crypto/cryptography_support.py b/plugins/module_utils/crypto/cryptography_support.py index ba622681..ef5c0738 100644 --- a/plugins/module_utils/crypto/cryptography_support.py +++ b/plugins/module_utils/crypto/cryptography_support.py @@ -242,7 +242,7 @@ def cryptography_name_to_oid(name): if dotted is None: if DOTTED_OID.match(name): return x509.oid.ObjectIdentifier(name) - raise OpenSSLObjectError('Cannot find OID for "{0}"'.format(name)) + raise OpenSSLObjectError(f'Cannot find OID for "{name}"') return x509.oid.ObjectIdentifier(dotted) @@ -297,7 +297,7 @@ else: def _parse_dn_component(name, sep=b",", decode_remainder=True): m = DN_COMPONENT_START_RE.match(name) if not m: - raise OpenSSLObjectError('cannot start part in "{0}"'.format(to_text(name))) + raise OpenSSLObjectError(f'cannot start part in "{to_text(name)}"') oid = cryptography_name_to_oid(to_text(m.group(1))) idx = len(m.group(0)) decoded_name = [] @@ -314,7 +314,7 @@ def _parse_dn_component(name, sep=b",", decode_remainder=True): idx2 = DN_HEX_LETTER.find(ch2.lower()) if idx1 < 0 or idx2 < 0: raise OpenSSLObjectError( - 'Invalid hex sequence entry "{0}"'.format(to_text(ch1 + ch2)) + f'Invalid hex sequence entry "{to_text(ch1 + ch2)}"' ) idx += 2 decoded_name.append(_int_to_byte(idx1 * 16 + idx2)) @@ -333,17 +333,13 @@ def _parse_dn_component(name, sep=b",", decode_remainder=True): if idx1 >= 0: if idx + 2 >= length: raise OpenSSLObjectError( - 'Hex escape sequence "\\{0}" incomplete at end of string'.format( - to_text(ch) - ) + f'Hex escape sequence "\\{to_text(ch)}" incomplete at end of string' ) ch2 = name[idx + 2 : idx + 3] idx2 = DN_HEX_LETTER.find(ch2.lower()) if idx2 < 0: raise OpenSSLObjectError( - 'Hex escape sequence "\\{0}" has invalid second letter'.format( - to_text(ch + ch2) - ) + f'Hex escape sequence "\\{to_text(ch + ch2)}" has invalid second letter' ) ch = _int_to_byte(idx1 * 16 + idx2) idx += 1 @@ -375,17 +371,13 @@ def _parse_dn(name): attribute, name = _parse_dn_component(name, sep=sep) except OpenSSLObjectError as e: raise OpenSSLObjectError( - 'Error while parsing distinguished name "{0}": {1}'.format( - to_text(original_name), e - ) + f'Error while parsing distinguished name "{to_text(original_name)}": {e}' ) result.append(attribute) if name: if name[0:1] != sep or len(name) < 2: raise OpenSSLObjectError( - 'Error while parsing distinguished name "{0}": unexpected end of string'.format( - to_text(original_name) - ) + f'Error while parsing distinguished name "{to_text(original_name)}": unexpected end of string' ) name = name[1:] return result @@ -398,9 +390,7 @@ def cryptography_parse_relative_distinguished_name(rdn): names.append(_parse_dn_component(to_bytes(part), decode_remainder=False)[0]) except OpenSSLObjectError as e: raise OpenSSLObjectError( - 'Error while parsing relative distinguished name "{0}": {1}'.format( - part, e - ) + f'Error while parsing relative distinguished name "{part}": {e}' ) return cryptography.x509.RelativeDistinguishedName(names) @@ -420,16 +410,14 @@ def _adjust_idn(value, idn_rewrite): if idn_rewrite == "idna" and _is_ascii(value): return value if idn_rewrite not in ("idna", "unicode"): - raise ValueError('Invalid value for idn_rewrite: "{0}"'.format(idn_rewrite)) + raise ValueError(f'Invalid value for idn_rewrite: "{idn_rewrite}"') if not HAS_IDNA: + what = "IDNA" if idn_rewrite == "unicode" else "Unicode" + dest = "Unicode" if idn_rewrite == "unicode" else "IDNA" raise OpenSSLObjectError( missing_required_lib( "idna", - reason='to transform {what} DNS name "{name}" to {dest}'.format( - name=value, - what="IDNA" if idn_rewrite == "unicode" else "Unicode", - dest="Unicode" if idn_rewrite == "unicode" else "IDNA", - ), + reason=f'to transform {what} DNS name "{value}" to {dest}', ) ) # Since IDNA does not like '*' or empty labels (except one empty label at the end), @@ -450,16 +438,11 @@ def _adjust_idn(value, idn_rewrite): elif idn_rewrite == "unicode" and part.startswith("xn--"): parts[index] = part.encode("ascii").decode("idna") except Exception as exc2003: + what = "IDNA" if idn_rewrite == "unicode" else "Unicode" + dest = "Unicode" if idn_rewrite == "unicode" else "IDNA" raise OpenSSLObjectError( - 'Error while transforming part "{part}" of {what} DNS name "{name}" to {dest}.' - ' IDNA2008 transformation resulted in "{exc2008}", IDNA2003 transformation resulted in "{exc2003}".'.format( - part=part, - name=value, - what="IDNA" if idn_rewrite == "unicode" else "Unicode", - dest="Unicode" if idn_rewrite == "unicode" else "IDNA", - exc2003=exc2003, - exc2008=exc2008, - ) + f'Error while transforming part "{part}" of {what} DNS name "{value}" to {dest}.' + f' IDNA2008 transformation resulted in "{exc2008}", IDNA2003 transformation resulted in "{exc2003}".' ) return ".".join(parts) @@ -468,18 +451,18 @@ def _adjust_idn_email(value, idn_rewrite): idx = value.find("@") if idx < 0: return value - return "{0}@{1}".format(value[:idx], _adjust_idn(value[idx + 1 :], idn_rewrite)) + return f"{value[:idx]}@{_adjust_idn(value[idx + 1:], idn_rewrite)}" def _adjust_idn_url(value, idn_rewrite): url = urlparse(value) host = _adjust_idn(url.hostname, idn_rewrite) if url.username is not None and url.password is not None: - host = "{0}:{1}@{2}".format(url.username, url.password, host) + host = f"{url.username}:{url.password}@{host}" elif url.username is not None: - host = "{0}@{1}".format(url.username, host) + host = f"{url.username}@{host}" if url.port is not None: - host = "{0}:{1}".format(host, url.port) + host = f"{host}:{url.port}" return urlunparse( ParseResult( scheme=url.scheme, @@ -514,9 +497,7 @@ def cryptography_get_name(name, what="Subject Alternative Name"): if name.startswith("RID:"): m = re.match(r"^([0-9]+(?:\.[0-9]+)*)$", to_text(name[4:])) if not m: - raise OpenSSLObjectError( - 'Cannot parse {what} "{name}"'.format(name=name, what=what) - ) + raise OpenSSLObjectError(f'Cannot parse {what} "{name}"') return x509.RegisteredID(x509.oid.ObjectIdentifier(m.group(1))) if name.startswith("otherName:"): # otherName can either be a raw ASN.1 hex string or in the format that OpenSSL works with. @@ -534,9 +515,9 @@ def cryptography_get_name(name, what="Subject Alternative Name"): name = to_text(name[10:], errors="surrogate_or_strict") if ";" not in name: raise OpenSSLObjectError( - 'Cannot parse {what} otherName "{name}", must be in the ' + f'Cannot parse {what} otherName "{name}", must be in the ' 'format "otherName:;" or ' - '"otherName:;"'.format(name=name, what=what) + '"otherName:;"' ) oid, value = name.split(";", 1) @@ -547,21 +528,13 @@ def cryptography_get_name(name, what="Subject Alternative Name"): x509.Name(reversed(_parse_dn(to_bytes(name[8:])))) ) except Exception as e: - raise OpenSSLObjectError( - 'Cannot parse {what} "{name}": {error}'.format( - name=name, what=what, error=e - ) - ) + raise OpenSSLObjectError(f'Cannot parse {what} "{name}": {e}') if ":" not in name: raise OpenSSLObjectError( - 'Cannot parse {what} "{name}" (forgot "DNS:" prefix?)'.format( - name=name, what=what - ) + f'Cannot parse {what} "{name}" (forgot "DNS:" prefix?)' ) raise OpenSSLObjectError( - 'Cannot parse {what} "{name}" (potentially unsupported by cryptography backend)'.format( - name=name, what=what - ) + f'Cannot parse {what} "{name}" (potentially unsupported by cryptography backend)' ) @@ -571,12 +544,12 @@ def _dn_escape_value(value): """ value = value.replace("\\", "\\\\") for ch in [",", "+", "<", ">", ";", '"']: - value = value.replace(ch, "\\%s" % ch) + value = value.replace(ch, f"\\{ch}") value = value.replace("\0", "\\00") if value.startswith((" ", "#")): - value = "\\%s" % value[0] + value[1:] + value = f"\\{value[0]}{value[1:]}" if value.endswith(" "): - value = value[:-1] + "\\ " + value = f"{value[:-1]}\\ " return value @@ -590,36 +563,29 @@ def cryptography_decode_name(name, idn_rewrite="ignore"): 'idn_rewrite must be one of "ignore", "idna", or "unicode"' ) if isinstance(name, x509.DNSName): - return "DNS:{0}".format(_adjust_idn(name.value, idn_rewrite)) + return f"DNS:{_adjust_idn(name.value, idn_rewrite)}" if isinstance(name, x509.IPAddress): if isinstance(name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)): - return "IP:{0}/{1}".format( - name.value.network_address.compressed, name.value.prefixlen - ) - return "IP:{0}".format(name.value.compressed) + return f"IP:{name.value.network_address.compressed}/{name.value.prefixlen}" + return f"IP:{name.value.compressed}" if isinstance(name, x509.RFC822Name): - return "email:{0}".format(_adjust_idn_email(name.value, idn_rewrite)) + return f"email:{_adjust_idn_email(name.value, idn_rewrite)}" if isinstance(name, x509.UniformResourceIdentifier): - return "URI:{0}".format(_adjust_idn_url(name.value, idn_rewrite)) + return f"URI:{_adjust_idn_url(name.value, idn_rewrite)}" if isinstance(name, x509.DirectoryName): # According to https://datatracker.ietf.org/doc/html/rfc4514.html#section-2.1 the # list needs to be reversed, and joined by commas return "dirName:" + ",".join( [ - "{0}={1}".format( - to_text(cryptography_oid_to_name(attribute.oid, short=True)), - _dn_escape_value(attribute.value), - ) + f"{to_text(cryptography_oid_to_name(attribute.oid, short=True))}={_dn_escape_value(attribute.value)}" for attribute in reversed(list(name.value)) ] ) if isinstance(name, x509.RegisteredID): - return "RID:{0}".format(name.value.dotted_string) + return f"RID:{name.value.dotted_string}" if isinstance(name, x509.OtherName): - return "otherName:{0};{1}".format( - name.type_id.dotted_string, _get_hex(name.value) - ) - raise OpenSSLObjectError('Cannot decode name "{0}"'.format(name)) + return f"otherName:{name.type_id.dotted_string};{_get_hex(name.value)}" + raise OpenSSLObjectError(f'Cannot decode name "{name}"') def _cryptography_get_keyusage(usage): @@ -645,7 +611,7 @@ def _cryptography_get_keyusage(usage): return "encipher_only" if usage in ("Decipher Only", "decipherOnly"): return "decipher_only" - raise OpenSSLObjectError('Unknown key usage "{0}"'.format(usage)) + raise OpenSSLObjectError(f'Unknown key usage "{usage}"') def cryptography_parse_key_usage_params(usages): @@ -685,9 +651,7 @@ def cryptography_get_basic_constraints(constraints): ca = False else: raise OpenSSLObjectError( - 'Unknown basic constraint value "{0}" for CA'.format( - constraint[3:] - ) + f'Unknown basic constraint value "{constraint[3:]}" for CA' ) elif constraint.startswith("pathlen:"): v = constraint[len("pathlen:") :] @@ -695,12 +659,10 @@ def cryptography_get_basic_constraints(constraints): path_length = int(v) except Exception as e: raise OpenSSLObjectError( - 'Cannot parse path length constraint "{0}" ({1})'.format(v, e) + f'Cannot parse path length constraint "{v}" ({e})' ) else: - raise OpenSSLObjectError( - 'Unknown basic constraint "{0}"'.format(constraint) - ) + raise OpenSSLObjectError(f'Unknown basic constraint "{constraint}"') return ca, path_length @@ -958,7 +920,7 @@ def cryptography_verify_signature(signature, data, hash_algorithm, signer_public signer_public_key.verify(signature, data) return True raise OpenSSLObjectError( - "Unsupported public key type {0}".format(type(signer_public_key)) + f"Unsupported public key type {type(signer_public_key)}" ) except InvalidSignature: return False diff --git a/plugins/module_utils/crypto/math.py b/plugins/module_utils/crypto/math.py index c9afa953..85046857 100644 --- a/plugins/module_utils/crypto/math.py +++ b/plugins/module_utils/crypto/math.py @@ -162,9 +162,9 @@ else: def _convert_int_to_bytes(count, n): if n == 0 and count == 0: return "" - h = "%x" % n + h = f"{n:x}" if len(h) > 2 * count: - raise Exception("Number {1} needs more than {0} bytes!".format(count, n)) + raise Exception(f"Number {n} needs more than {count} bytes!") return ("0" * (2 * count - len(h)) + h).decode("hex") def _convert_bytes_to_int(data): @@ -174,7 +174,7 @@ else: return v def _to_hex(no): - return "%x" % no + return f"{no:x}" def convert_int_to_bytes(no, count=None): diff --git a/plugins/module_utils/crypto/module_backends/certificate.py b/plugins/module_utils/crypto/module_backends/certificate.py index 88e4418e..6bbfd18c 100644 --- a/plugins/module_utils/crypto/module_backends/certificate.py +++ b/plugins/module_utils/crypto/module_backends/certificate.py @@ -363,16 +363,14 @@ def select_backend(module, backend, provider): # Fail if no backend has been found if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library " "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) diff --git a/plugins/module_utils/crypto/module_backends/certificate_acme.py b/plugins/module_utils/crypto/module_backends/certificate_acme.py index 2d7ca1e1..0c13e644 100644 --- a/plugins/module_utils/crypto/module_backends/certificate_acme.py +++ b/plugins/module_utils/crypto/module_backends/certificate_acme.py @@ -31,17 +31,17 @@ class AcmeCertificateBackend(CertificateBackend): ) if self.csr_content is None and not os.path.exists(self.csr_path): raise CertificateError( - "The certificate signing request file %s does not exist" % self.csr_path + f"The certificate signing request file {self.csr_path} does not exist" ) if not os.path.exists(self.accountkey_path): raise CertificateError( - "The account key %s does not exist" % self.accountkey_path + f"The account key {self.accountkey_path} does not exist" ) if not os.path.exists(self.challenge_path): raise CertificateError( - "The challenge path %s does not exist" % self.challenge_path + f"The challenge path {self.challenge_path} does not exist" ) self.acme_tiny_path = self.module.get_bin_path("acme-tiny", required=True) @@ -66,7 +66,7 @@ class AcmeCertificateBackend(CertificateBackend): except Exception: pass self.module.fail_json( - msg="failed to create temporary CSR file: %s" % to_native(err), + msg=f"failed to create temporary CSR file: {to_native(err)}", exception=traceback.format_exc(), ) f.close() diff --git a/plugins/module_utils/crypto/module_backends/certificate_entrust.py b/plugins/module_utils/crypto/module_backends/certificate_entrust.py index 3cc827ec..e04e8427 100644 --- a/plugins/module_utils/crypto/module_backends/certificate_entrust.py +++ b/plugins/module_utils/crypto/module_backends/certificate_entrust.py @@ -56,9 +56,7 @@ class EntrustCertificateBackend(CertificateBackend): ) if self.csr_content is None and not os.path.exists(self.csr_path): raise CertificateError( - "The certificate signing request file {0} does not exist".format( - self.csr_path - ) + f"The certificate signing request file {self.csr_path} does not exist" ) self._ensure_csr_loaded() @@ -77,7 +75,7 @@ class EntrustCertificateBackend(CertificateBackend): self.module.fail_json( msg=( "Entrust provider does not currently support multiple validated organizations. Multiple organizations found in " - "Subject DN: '{0}'. ".format(self.csr.subject) + f"Subject DN: '{self.csr.subject}'. " ) ) # If no organization in the CSR, explicitly tell ECS that it should be blank in issued cert, not defaulted to @@ -98,11 +96,7 @@ class EntrustCertificateBackend(CertificateBackend): ], ) except SessionConfigurationException as e: - module.fail_json( - msg="Failed to initialize Entrust Provider: {0}".format( - to_native(e.message) - ) - ) + module.fail_json(msg=f"Failed to initialize Entrust Provider: {e.message}") def generate_certificate(self): """(Re-)Generate certificate.""" @@ -138,9 +132,7 @@ class EntrustCertificateBackend(CertificateBackend): self.trackingId = result.get("trackingId") except RestOperationException as e: self.module.fail_json( - msg="Failed to request new certificate from Entrust Certificate Services (ECS): {0}".format( - to_native(e.message) - ) + msg=f"Failed to request new certificate from Entrust Certificate Services (ECS): {e.message}" ) self.cert_bytes = to_bytes(result.get("endEntityCert")) @@ -159,9 +151,7 @@ class EntrustCertificateBackend(CertificateBackend): cert_details = self._get_cert_details() except RestOperationException as e: self.module.fail_json( - msg="Failed to get status of existing certificate from Entrust Certificate Services (ECS): {0}.".format( - to_native(e.message) - ) + msg=f"Failed to get status of existing certificate from Entrust Certificate Services (ECS): {e.message}." ) # Always issue a new certificate if the certificate is expired, suspended or revoked @@ -189,8 +179,8 @@ class EntrustCertificateBackend(CertificateBackend): serial_number = None expiry = None if self.backend == "cryptography": - serial_number = "{0:X}".format( - cryptography_serial_number_of_cert(self.existing_certificate) + serial_number = ( + f"{cryptography_serial_number_of_cert(self.existing_certificate):X}" ) expiry = get_not_valid_after(self.existing_certificate) diff --git a/plugins/module_utils/crypto/module_backends/certificate_info.py b/plugins/module_utils/crypto/module_backends/certificate_info.py index 6bcb7a8d..8a7b1e68 100644 --- a/plugins/module_utils/crypto/module_backends/certificate_info.py +++ b/plugins/module_utils/crypto/module_backends/certificate_info.py @@ -332,11 +332,9 @@ class CertificateInfoRetrievalCryptography(CertificateInfoRetrieval): x509.BasicConstraints ) result = [] - result.append( - "CA:{0}".format("TRUE" if ext_keyusage_ext.value.ca else "FALSE") - ) + result.append(f"CA:{'TRUE' if ext_keyusage_ext.value.ca else 'FALSE'}") if ext_keyusage_ext.value.path_length is not None: - result.append("pathlen:{0}".format(ext_keyusage_ext.value.path_length)) + result.append(f"pathlen:{ext_keyusage_ext.value.path_length}") return sorted(result), ext_keyusage_ext.critical except cryptography.x509.ExtensionNotFound: return None, False @@ -474,20 +472,17 @@ def select_backend(module, backend, content): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect any of the required Python libraries " - "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) return backend, CertificateInfoRetrievalCryptography(module, content) else: - raise ValueError("Unsupported value for backend: {0}".format(backend)) + raise ValueError(f"Unsupported value for backend: {backend}") diff --git a/plugins/module_utils/crypto/module_backends/certificate_ownca.py b/plugins/module_utils/crypto/module_backends/certificate_ownca.py index e617b6fb..3f49c936 100644 --- a/plugins/module_utils/crypto/module_backends/certificate_ownca.py +++ b/plugins/module_utils/crypto/module_backends/certificate_ownca.py @@ -93,21 +93,17 @@ class OwnCACertificateBackendCryptography(CertificateBackend): ) if self.csr_content is None and not os.path.exists(self.csr_path): raise CertificateError( - "The certificate signing request file {0} does not exist".format( - self.csr_path - ) + f"The certificate signing request file {self.csr_path} does not exist" ) if self.ca_cert_content is None and not os.path.exists(self.ca_cert_path): raise CertificateError( - "The CA certificate file {0} does not exist".format(self.ca_cert_path) + f"The CA certificate file {self.ca_cert_path} does not exist" ) if self.ca_privatekey_content is None and not os.path.exists( self.ca_privatekey_path ): raise CertificateError( - "The CA private key file {0} does not exist".format( - self.ca_privatekey_path - ) + f"The CA private key file {self.ca_privatekey_path} does not exist" ) self._ensure_csr_loaded() @@ -134,8 +130,7 @@ class OwnCACertificateBackendCryptography(CertificateBackend): if cryptography_key_needs_digest_for_signing(self.ca_private_key): if self.digest is None: raise CertificateError( - "The digest %s is not supported with the cryptography backend" - % module.params["ownca_digest"] + f"The digest {module.params['ownca_digest']} is not supported with the cryptography backend" ) else: self.digest = None diff --git a/plugins/module_utils/crypto/module_backends/certificate_selfsigned.py b/plugins/module_utils/crypto/module_backends/certificate_selfsigned.py index 1a4589d6..33d62721 100644 --- a/plugins/module_utils/crypto/module_backends/certificate_selfsigned.py +++ b/plugins/module_utils/crypto/module_backends/certificate_selfsigned.py @@ -67,13 +67,11 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend): if self.csr_path is not None and not os.path.exists(self.csr_path): raise CertificateError( - "The certificate signing request file {0} does not exist".format( - self.csr_path - ) + f"The certificate signing request file {self.csr_path} does not exist" ) if self.privatekey_content is None and not os.path.exists(self.privatekey_path): raise CertificateError( - "The private key file {0} does not exist".format(self.privatekey_path) + f"The private key file {self.privatekey_path} does not exist" ) self._module = module @@ -90,9 +88,7 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend): digest = self.digest if digest is None: self.module.fail_json( - msg='Unsupported digest "{0}"'.format( - module.params["selfsigned_digest"] - ) + msg=f'Unsupported digest "{module.params["selfsigned_digest"]}"' ) try: self.csr = csr.sign(self.privatekey, digest, default_backend()) @@ -109,8 +105,7 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend): if cryptography_key_needs_digest_for_signing(self.privatekey): if self.digest is None: raise CertificateError( - "The digest %s is not supported with the cryptography backend" - % module.params["selfsigned_digest"] + f"The digest {module.params['selfsigned_digest']} is not supported with the cryptography backend" ) else: self.digest = None diff --git a/plugins/module_utils/crypto/module_backends/crl_info.py b/plugins/module_utils/crypto/module_backends/crl_info.py index 7682e155..a2c763d6 100644 --- a/plugins/module_utils/crypto/module_backends/crl_info.py +++ b/plugins/module_utils/crypto/module_backends/crl_info.py @@ -58,7 +58,7 @@ class CRLInfoRetrieval: else: self.crl = x509.load_der_x509_crl(self.content, default_backend()) except ValueError as e: - self.module.fail_json(msg="Error while decoding CRL: {0}".format(e)) + self.module.fail_json(msg=f"Error while decoding CRL: {e}") result = { "changed": False, @@ -96,9 +96,7 @@ class CRLInfoRetrieval: def get_crl_info(module, content, list_revoked_certificates=True): if not CRYPTOGRAPHY_FOUND: module.fail_json( - msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) - ), + msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"), exception=CRYPTOGRAPHY_IMP_ERR, ) diff --git a/plugins/module_utils/crypto/module_backends/csr.py b/plugins/module_utils/crypto/module_backends/csr.py index 0a7ef636..df366843 100644 --- a/plugins/module_utils/crypto/module_backends/csr.py +++ b/plugins/module_utils/crypto/module_backends/csr.py @@ -163,7 +163,7 @@ class CertificateSigningRequestBackend: if not self.subjectAltName and module.params["use_common_name_for_san"]: for sub in self.subject: if sub[0] in ("commonName", "CN"): - self.subjectAltName = ["DNS:%s" % sub[1]] + self.subjectAltName = [f"DNS:{sub[1]}"] self.using_common_name_for_san = True break @@ -174,7 +174,7 @@ class CertificateSigningRequestBackend: ) except Exception as e: raise CertificateSigningRequestError( - "Cannot parse subject_key_identifier: {0}".format(e) + f"Cannot parse subject_key_identifier: {e}" ) if self.authority_key_identifier is not None: @@ -184,7 +184,7 @@ class CertificateSigningRequestBackend: ) except Exception as e: raise CertificateSigningRequestError( - "Cannot parse authority_key_identifier: {0}".format(e) + f"Cannot parse authority_key_identifier: {e}" ) self.existing_csr = None @@ -337,9 +337,7 @@ def parse_crl_distribution_points(module, crl_distribution_points): result.append(cryptography.x509.DistributionPoint(**params)) except (OpenSSLObjectError, ValueError) as e: raise OpenSSLObjectError( - "Error while parsing CRL distribution point #{index}: {error}".format( - index=index, error=e - ) + f"Error while parsing CRL distribution point #{index}: {e}" ) return result @@ -446,9 +444,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack critical=self.name_constraints_critical, ) except TypeError as e: - raise OpenSSLObjectError( - "Error while parsing name constraint: {0}".format(e) - ) + raise OpenSSLObjectError(f"Error while parsing name constraint: {e}") if self.create_subject_key_identifier: csr = csr.add_extension( @@ -494,7 +490,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack digest = select_message_digest(self.digest) if digest is None: raise CertificateSigningRequestError( - 'Unsupported digest "{0}"'.format(self.digest) + f'Unsupported digest "{self.digest}"' ) try: self.csr = csr.sign(self.privatekey, digest, self.cryptography_backend) @@ -518,7 +514,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack # https://github.com/kjd/idna/commit/ebefacd3134d0f5da4745878620a6a1cba86d130 # and then # https://github.com/kjd/idna/commit/ea03c7b5db7d2a99af082e0239da2b68aeea702a). - msg = "Error while creating CSR: {0}\n".format(e) + msg = f"Error while creating CSR: {e}\n" if self.using_common_name_for_san: self.module.fail_json( msg=msg @@ -813,23 +809,20 @@ def select_backend(module, backend): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect any of the required Python libraries " - "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) return backend, CertificateSigningRequestCryptographyBackend(module) else: - raise Exception("Unsupported value for backend: {0}".format(backend)) + raise Exception(f"Unsupported value for backend: {backend}") def get_csr_argument_spec(): diff --git a/plugins/module_utils/crypto/module_backends/csr_info.py b/plugins/module_utils/crypto/module_backends/csr_info.py index 6af0cb10..c512caf7 100644 --- a/plugins/module_utils/crypto/module_backends/csr_info.py +++ b/plugins/module_utils/crypto/module_backends/csr_info.py @@ -258,9 +258,9 @@ class CSRInfoRetrievalCryptography(CSRInfoRetrieval): ext_keyusage_ext = self.csr.extensions.get_extension_for_class( x509.BasicConstraints ) - result = ["CA:{0}".format("TRUE" if ext_keyusage_ext.value.ca else "FALSE")] + result = [f"CA:{'TRUE' if ext_keyusage_ext.value.ca else 'FALSE'}"] if ext_keyusage_ext.value.path_length is not None: - result.append("pathlen:{0}".format(ext_keyusage_ext.value.path_length)) + result.append(f"pathlen:{ext_keyusage_ext.value.path_length}") return sorted(result), ext_keyusage_ext.critical except cryptography.x509.ExtensionNotFound: return None, False @@ -380,16 +380,14 @@ def select_backend(module, backend, content, validate_signature=True): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library " "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) @@ -397,4 +395,4 @@ def select_backend(module, backend, content, validate_signature=True): module, content, validate_signature=validate_signature ) else: - raise ValueError("Unsupported value for backend: {0}".format(backend)) + raise ValueError(f"Unsupported value for backend: {backend}") diff --git a/plugins/module_utils/crypto/module_backends/privatekey.py b/plugins/module_utils/crypto/module_backends/privatekey.py index 1d53e81b..d4022a1f 100644 --- a/plugins/module_utils/crypto/module_backends/privatekey.py +++ b/plugins/module_utils/crypto/module_backends/privatekey.py @@ -273,7 +273,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend): ecclass = cryptography.hazmat.primitives.asymmetric.ec.__dict__.get(ectype) if ecclass is None: self.module.fail_json( - msg="Your cryptography version does not support {0}".format(ectype) + msg=f"Your cryptography version does not support {ectype}" ) return ecclass @@ -385,9 +385,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend): if self.type == "ECC" and self.curve in self.curves: if self.curves[self.curve]["deprecated"]: self.module.warn( - "Elliptic curves of type {0} should not be used for new keys!".format( - self.curve - ) + f"Elliptic curves of type {self.curve} should not be used for new keys!" ) self.private_key = ( cryptography.hazmat.primitives.asymmetric.ec.generate_private_key( @@ -397,9 +395,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend): ) except cryptography.exceptions.UnsupportedAlgorithm: self.module.fail_json( - msg="Cryptography backend does not support the algorithm required for {0}".format( - self.type - ) + msg=f"Cryptography backend does not support the algorithm required for {self.type}" ) def get_private_key_data(self): @@ -426,9 +422,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend): ) except AttributeError: self.module.fail_json( - msg='Cryptography backend does not support the selected output format "{0}"'.format( - self.format - ) + msg=f'Cryptography backend does not support the selected output format "{self.format}"' ) # Select key encryption @@ -454,15 +448,11 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend): ) except ValueError: self.module.fail_json( - msg='Cryptography backend cannot serialize the private key in the required format "{0}"'.format( - self.format - ) + msg=f'Cryptography backend cannot serialize the private key in the required format "{self.format}"' ) except Exception: self.module.fail_json( - msg='Error while serializing the private key in the required format "{0}"'.format( - self.format - ), + msg=f'Error while serializing the private key in the required format "{self.format}"', exception=traceback.format_exc(), ) @@ -611,21 +601,19 @@ def select_backend(module, backend): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library " "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) return backend, PrivateKeyCryptographyBackend(module) else: - raise Exception("Unsupported value for backend: {0}".format(backend)) + raise Exception(f"Unsupported value for backend: {backend}") def get_privatekey_argument_spec(): diff --git a/plugins/module_utils/crypto/module_backends/privatekey_convert.py b/plugins/module_utils/crypto/module_backends/privatekey_convert.py index 094880aa..53d93ce7 100644 --- a/plugins/module_utils/crypto/module_backends/privatekey_convert.py +++ b/plugins/module_utils/crypto/module_backends/privatekey_convert.py @@ -161,9 +161,7 @@ class PrivateKeyConvertCryptographyBackend(PrivateKeyConvertBackend): ) except AttributeError: self.module.fail_json( - msg='Cryptography backend does not support the selected output format "{0}"'.format( - self.format - ) + msg=f'Cryptography backend does not support the selected output format "{self.format}"' ) # Select key encryption @@ -186,15 +184,11 @@ class PrivateKeyConvertCryptographyBackend(PrivateKeyConvertBackend): ) except ValueError: self.module.fail_json( - msg='Cryptography backend cannot serialize the private key in the required format "{0}"'.format( - self.format - ) + msg=f'Cryptography backend cannot serialize the private key in the required format "{self.format}"' ) except Exception: self.module.fail_json( - msg='Error while serializing the private key in the required format "{0}"'.format( - self.format - ), + msg=f'Error while serializing the private key in the required format "{self.format}"', exception=traceback.format_exc(), ) @@ -285,9 +279,7 @@ class PrivateKeyConvertCryptographyBackend(PrivateKeyConvertBackend): def select_backend(module): if not CRYPTOGRAPHY_FOUND: module.fail_json( - msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) - ), + msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"), exception=CRYPTOGRAPHY_IMP_ERR, ) return PrivateKeyConvertCryptographyBackend(module) diff --git a/plugins/module_utils/crypto/module_backends/privatekey_info.py b/plugins/module_utils/crypto/module_backends/privatekey_info.py index aa67085f..caa4b8bf 100644 --- a/plugins/module_utils/crypto/module_backends/privatekey_info.py +++ b/plugins/module_utils/crypto/module_backends/privatekey_info.py @@ -173,7 +173,7 @@ def _is_cryptography_key_consistent( return False # For X25519 and X448, there's no test yet. if warn_func is not None: - warn_func("Cannot determine consistency for key of type %s" % type(key)) + warn_func(f"Cannot determine consistency for key of type {type(key)}") return None @@ -338,16 +338,14 @@ def select_backend( # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library " "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) @@ -359,4 +357,4 @@ def select_backend( check_consistency=check_consistency, ) else: - raise ValueError("Unsupported value for backend: {0}".format(backend)) + raise ValueError(f"Unsupported value for backend: {backend}") diff --git a/plugins/module_utils/crypto/module_backends/publickey_info.py b/plugins/module_utils/crypto/module_backends/publickey_info.py index 4b1e2c6d..2a85885d 100644 --- a/plugins/module_utils/crypto/module_backends/publickey_info.py +++ b/plugins/module_utils/crypto/module_backends/publickey_info.py @@ -84,7 +84,7 @@ def _get_cryptography_public_key_info(key): key_public_data["y"] = public_numbers.y key_public_data["exponent_size"] = key.curve.key_size else: - key_type = "unknown ({0})".format(type(key)) + key_type = f"unknown ({type(key)})" return key_type, key_public_data @@ -174,17 +174,14 @@ def select_backend(module, backend, content=None, key=None): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect any of the required Python libraries " - "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) @@ -192,4 +189,4 @@ def select_backend(module, backend, content=None, key=None): module, content=content, key=key ) else: - raise ValueError("Unsupported value for backend: {0}".format(backend)) + raise ValueError(f"Unsupported value for backend: {backend}") diff --git a/plugins/module_utils/crypto/pem.py b/plugins/module_utils/crypto/pem.py index 1d2e8381..603cb562 100644 --- a/plugins/module_utils/crypto/pem.py +++ b/plugins/module_utils/crypto/pem.py @@ -98,36 +98,24 @@ def _extract_type(line, start=PEM_START): def extract_pem(content, strict=False): lines = content.splitlines() if len(lines) < 3: - raise ValueError( - "PEM must have at least 3 lines, have only {count}".format(count=len(lines)) - ) + raise ValueError(f"PEM must have at least 3 lines, have only {len(lines)}") header_type = _extract_type(lines[0]) if header_type is None: raise ValueError( - "First line is not of format {start}...{end}: {line!r}".format( - start=PEM_START, end=PEM_END, line=lines[0] - ) + f"First line is not of format {PEM_START}...{PEM_END}: {lines[0]!r}" ) footer_type = _extract_type(lines[-1], start=PEM_END_START) if strict: if header_type != footer_type: raise ValueError( - "Header type ({header}) is different from footer type ({footer})".format( - header=header_type, footer=footer_type - ) + f"Header type ({header_type}) is different from footer type ({footer_type})" ) for idx, line in enumerate(lines[1:-2]): if len(line) != 64: - raise ValueError( - "Line {idx} has length {len} instead of 64".format( - idx=idx, len=len(line) - ) - ) + raise ValueError(f"Line {idx} has length {len(line)} instead of 64") if not (0 < len(lines[-2]) <= 64): raise ValueError( - "Last line has length {len}, should be in (0, 64]".format( - len=len(lines[-2]) - ) + f"Last line has length {len(lines[-2])}, should be in (0, 64]" ) content = lines[1:-1] return header_type, "".join(content) diff --git a/plugins/module_utils/crypto/support.py b/plugins/module_utils/crypto/support.py index 144d5ac8..04d085a6 100644 --- a/plugins/module_utils/crypto/support.py +++ b/plugins/module_utils/crypto/support.py @@ -179,7 +179,7 @@ def load_publickey(path=None, content=None, backend=None): content, backend=cryptography_backend() ) except Exception as e: - raise OpenSSLObjectError("Error while deserializing key: {0}".format(e)) + raise OpenSSLObjectError(f"Error while deserializing key: {e}") def load_certificate( @@ -209,9 +209,7 @@ def load_certificate( cert_content, cryptography_backend() ) except ValueError as exc: - raise OpenSSLObjectError( - "Cannot parse DER certificate: {0}".format(exc) - ) + raise OpenSSLObjectError(f"Cannot parse DER certificate: {exc}") def load_certificate_request(path, content=None, backend="cryptography"): @@ -241,31 +239,30 @@ def parse_name_field(input_dict, name_field_name=None): for entry in value: if not isinstance(entry, six.string_types): raise TypeError( - ("Values %s must be strings" % error_str).format( + f"Values {error_str} must be strings".format( key=key, name=name_field_name ) ) if not entry: raise ValueError( - ("Values for %s must not be empty strings" % error_str).format( - key=key + f"Values for {error_str} must not be empty strings".format( + key=key, name=name_field_name ) ) result.append((key, entry)) elif isinstance(value, six.string_types): if not value: raise ValueError( - ("Value for %s must not be an empty string" % error_str).format( - key=key + f"Value for {error_str} must not be an empty string".format( + key=key, name=name_field_name ) ) result.append((key, value)) else: raise TypeError( ( - "Value for %s must be either a string or a list of strings" - % error_str - ).format(key=key) + f"Value for {error_str} must be either a string or a list of strings" + ).format(key=key, name=name_field_name) ) return result @@ -277,17 +274,13 @@ def parse_ordered_name_field(input_list, name_field_name): for index, entry in enumerate(input_list): if len(entry) != 1: raise ValueError( - "Entry #{index} in {name} must be a dictionary with exactly one key-value pair".format( - name=name_field_name, index=index + 1 - ) + f"Entry #{index + 1} in {name_field_name} must be a dictionary with exactly one key-value pair" ) try: result.extend(parse_name_field(entry, name_field_name=name_field_name)) except (TypeError, ValueError) as exc: raise ValueError( - "Error while processing entry #{index} in {name}: {error}".format( - name=name_field_name, index=index + 1, error=exc - ) + f"Error while processing entry #{index + 1} in {name_field_name}: {exc}" ) return result diff --git a/plugins/module_utils/ecs/api.py b/plugins/module_utils/ecs/api.py index 79642e32..146d8867 100644 --- a/plugins/module_utils/ecs/api.py +++ b/plugins/module_utils/ecs/api.py @@ -73,12 +73,8 @@ def generate_docstring(operation_spec): if len(parameters) != 0: docs += "\tArguments:\n\n" for parameter in parameters: - docs += "{0} ({1}:{2}): {3}\n".format( - parameter.get("name"), - parameter.get("type", "No Type"), - "Required" if parameter.get("required", False) else "Not Required", - parameter.get("description"), - ) + req = "Required" if parameter.get("required", False) else "Not Required" + docs += f"{parameter.get('name')} ({parameter.get('type', 'No Type')}:{req}): {parameter.get('description')}\n" return docs @@ -104,11 +100,8 @@ class RestOperation: self.parameters = {} else: self.parameters = parameters - self.url = "{scheme}://{host}{base_path}{uri}".format( - scheme="https", - host=session._spec.get("host"), - base_path=session._spec.get("basePath"), - uri=uri, + self.url = ( + f"https://{session._spec.get('host')}{session._spec.get('basePath')}{uri}" ) def restmethod(self, *args, **kwargs): @@ -204,7 +197,7 @@ class Resource: operation_name = "Patch" else: raise SessionConfigurationException( - to_native("Invalid REST method type {0}".format(method)) + to_native(f"Invalid REST method type {method}") ) # Get the non-parameter parts of the URL and append to the operation name @@ -286,9 +279,7 @@ class ECSSession: ): raise SessionConfigurationException( to_native( - "OpenAPI specification was not found at location {0}.".format( - entrust_api_specification_path - ) + f"OpenAPI specification was not found at location {entrust_api_specification_path}." ) ) if not valid_file_format.match(entrust_api_specification_path): @@ -315,9 +306,7 @@ class ECSSession: except HTTPError as e: raise SessionConfigurationException( to_native( - "Error downloading specification from address '{0}', received error code '{1}'".format( - entrust_api_specification_path, e.getcode() - ) + f"Error downloading specification from address '{entrust_api_specification_path}', received error code '{e.getcode()}'" ) ) else: @@ -344,9 +333,8 @@ class ECSSession: ): raise SessionConfigurationException( to_native( - "Parameter provided for entrust_api_specification_path of value '{0}' was not a valid file path or HTTPS address.".format( - entrust_api_specification_path - ) + f"Parameter provided for entrust_api_specification_path of value '{entrust_api_specification_path}'" + " was not a valid file path or HTTPS address." ) ) @@ -355,18 +343,14 @@ class ECSSession: if not file_path or not os.path.isfile(file_path): raise SessionConfigurationException( to_native( - "Parameter provided for {0} of value '{1}' was not a valid file path.".format( - required_file, file_path - ) + f"Parameter provided for {required_file} of value '{file_path}' was not a valid file path." ) ) for required_var in ["entrust_api_user", "entrust_api_key"]: if not kwargs.get(required_var): raise SessionConfigurationException( - to_native( - "Parameter provided for {0} was missing.".format(required_var) - ) + to_native(f"Parameter provided for {required_var} was missing.") ) config["entrust_api_cert"] = kwargs.get("entrust_api_cert") diff --git a/plugins/module_utils/gnupg/cli.py b/plugins/module_utils/gnupg/cli.py index 31e45a6c..ff7d00e1 100644 --- a/plugins/module_utils/gnupg/cli.py +++ b/plugins/module_utils/gnupg/cli.py @@ -39,19 +39,15 @@ def get_fingerprint_from_stdout(stdout): parts = line.split(":") if len(parts) <= 9 or not parts[9]: raise GPGError( - 'Result line "{line}" does not have fingerprint as 10th component'.format( - line=line - ) + f'Result line "{line}" does not have fingerprint as 10th component' ) return parts[9] - raise GPGError( - 'Cannot extract fingerprint from stdout "{stdout}"'.format(stdout=stdout) - ) + raise GPGError(f'Cannot extract fingerprint from stdout "{stdout}"') def get_fingerprint_from_file(gpg_runner, path): if not os.path.exists(path): - raise GPGError("{path} does not exist".format(path=path)) + raise GPGError(f"{path} does not exist") stdout = gpg_runner.run_command( [ "--no-keyring", diff --git a/plugins/module_utils/io.py b/plugins/module_utils/io.py index 9e676b60..3fa166d2 100644 --- a/plugins/module_utils/io.py +++ b/plugins/module_utils/io.py @@ -19,7 +19,7 @@ def load_file(path, module=None): except Exception as exc: if module is None: raise - module.fail_json("Error while loading {0} - {1}".format(path, str(exc))) + module.fail_json(f"Error while loading {path} - {exc}") def load_file_if_exists(path, module=None, ignore_errors=False): @@ -40,13 +40,13 @@ def load_file_if_exists(path, module=None, ignore_errors=False): return None if module is None: raise - module.fail_json("Error while loading {0} - {1}".format(path, str(exc))) + module.fail_json(f"Error while loading {path} - {exc}") except Exception as exc: if ignore_errors: return None if module is None: raise - module.fail_json("Error while loading {0} - {1}".format(path, str(exc))) + module.fail_json(f"Error while loading {path} - {exc}") def write_file(module, content, default_mode=None, path=None): @@ -83,9 +83,7 @@ def write_file(module, content, default_mode=None, path=None): os.remove(tmp_name) except Exception: pass - module.fail_json( - msg="Error while writing result into temporary file: {0}".format(e) - ) + module.fail_json(msg=f"Error while writing result into temporary file: {e}") # Update destination to wanted permissions if os.path.exists(file_args["path"]): module.set_fs_attributes_if_different(file_args, False) @@ -101,4 +99,4 @@ def write_file(module, content, default_mode=None, path=None): os.remove(tmp_name) except Exception: pass - module.fail_json(msg="Error while writing result: {0}".format(e)) + module.fail_json(msg=f"Error while writing result: {e}") diff --git a/plugins/module_utils/openssh/backends/common.py b/plugins/module_utils/openssh/backends/common.py index e82a2302..2d48b880 100644 --- a/plugins/module_utils/openssh/backends/common.py +++ b/plugins/module_utils/openssh/backends/common.py @@ -73,7 +73,7 @@ class OpensshModule: self._execute() except Exception as e: self.module.fail_json( - msg="unexpected error occurred: %s" % to_native(e), + msg=f"unexpected error occurred: {to_native(e)}", exception=traceback.format_exc(), ) @@ -125,8 +125,7 @@ class OpensshModule: if not os.path.isdir(base_dir): self.module.fail_json( name=base_dir, - msg="The directory %s does not exist or the file is not a directory" - % base_dir, + msg=f"The directory {base_dir} does not exist or the file is not a directory", ) def _get_ssh_version(self): @@ -253,8 +252,7 @@ class KeygenCommand: os.chmod(private_key_path, stat.S_IWUSR + stat.S_IRUSR) except (IOError, OSError) as e: raise e( - "The private key at %s is not writeable preventing a comment update" - % private_key_path + f"The private key at {private_key_path} is not writeable preventing a comment update" ) command = [self._bin_path, "-q"] @@ -332,7 +330,7 @@ class PublicKey: return not self == other def __str__(self): - return "%s %s" % (self._type_string, self._data) + return f"{self._type_string} {self._data}" @property def comment(self): diff --git a/plugins/module_utils/openssh/backends/keypair_backend.py b/plugins/module_utils/openssh/backends/keypair_backend.py index b02d2406..b076ff0b 100644 --- a/plugins/module_utils/openssh/backends/keypair_backend.py +++ b/plugins/module_utils/openssh/backends/keypair_backend.py @@ -90,7 +90,7 @@ class KeypairBackend(OpensshModule): result = 256 else: return self.module.fail_json( - msg="%s is not a valid value for key type" % self.type + msg=f"{self.type} is not a valid value for key type" ) return result @@ -100,8 +100,7 @@ class KeypairBackend(OpensshModule): if os.path.isdir(self.private_key_path): self.module.fail_json( - msg="%s is a directory. Please specify a path to a file." - % self.private_key_path + msg=f"{self.private_key_path} is a directory. Please specify a path to a file." ) def _execute(self): @@ -562,4 +561,4 @@ def select_backend(module, backend): module.fail_json(msg=missing_required_lib("cryptography >= 2.6")) return backend, KeypairBackendCryptography(module) else: - raise ValueError("Unsupported value for backend: {0}".format(backend)) + raise ValueError(f"Unsupported value for backend: {backend}") diff --git a/plugins/module_utils/openssh/certificate.py b/plugins/module_utils/openssh/certificate.py index bd7e8f10..e9035f07 100644 --- a/plugins/module_utils/openssh/certificate.py +++ b/plugins/module_utils/openssh/certificate.py @@ -110,8 +110,7 @@ class OpensshCertificateTimeParameters: if self._valid_from > self._valid_to: raise ValueError( - "Valid from: %s must not be greater than Valid to: %s" - % (valid_from, valid_to) + f"Valid from: {valid_from} must not be greater than Valid to: {valid_to}" ) def __eq__(self, other): @@ -129,10 +128,7 @@ class OpensshCertificateTimeParameters: @property def validity_string(self): if not (self._valid_from == _ALWAYS and self._valid_to == _FOREVER): - return "%s:%s" % ( - self.valid_from(date_format="openssh"), - self.valid_to(date_format="openssh"), - ) + return f"{self.valid_from(date_format='openssh')}:{self.valid_to(date_format='openssh')}" return "" def valid_from(self, date_format): @@ -166,7 +162,7 @@ class OpensshCertificateTimeParameters: (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 ) else: - raise ValueError("%s is not a valid format" % date_format) + raise ValueError(f"{date_format} is not a valid format") return result @staticmethod @@ -182,8 +178,7 @@ class OpensshCertificateTimeParameters: ) else: raise ValueError( - "Value must be of type (str, unicode, int, long) not %s" - % type(time_string_or_timestamp) + f"Value must be of type (str, unicode, int, long) not {type(time_string_or_timestamp)}" ) except ValueError: raise @@ -238,10 +233,10 @@ class OpensshCertificateOption: raise ValueError("type must be either 'critical' or 'extension'") if not isinstance(name, six.string_types): - raise TypeError("name must be a string not %s" % type(name)) + raise TypeError(f"name must be a string not {type(name)}") if not isinstance(data, six.string_types): - raise TypeError("data must be a string not %s" % type(data)) + raise TypeError(f"data must be a string not {type(data)}") self._option_type = option_type self._name = name.lower() @@ -267,7 +262,7 @@ class OpensshCertificateOption: def __str__(self): if self._data: - return "%s=%s" % (self._name, self._data) + return f"{self._name}={self._data}" return self._name @property @@ -286,7 +281,7 @@ class OpensshCertificateOption: def from_string(cls, option_string): if not isinstance(option_string, six.string_types): raise ValueError( - "option_string must be a string not %s" % type(option_string) + f"option_string must be a string not {type(option_string)}" ) option_type = None @@ -356,7 +351,7 @@ class OpensshCertificateInfo: elif cert_type == "host" or cert_type == _HOST_TYPE: self._cert_type = _HOST_TYPE else: - raise ValueError("%s is not a valid certificate type" % cert_type) + raise ValueError(f"{cert_type} is not a valid certificate type") def signing_key_fingerprint(self): return fingerprint(self.signing_key) @@ -447,8 +442,7 @@ class OpensshECDSACertificateInfo(OpensshCertificateInfo): ) else: raise ValueError( - "Curve must be one of %s" - % (b",".join(list(_ECDSA_CURVE_IDENTIFIERS.values()))).decode("UTF-8") + "Curve must be one of {(b','.join(_ECDSA_CURVE_IDENTIFIERS.values())).decode('UTF-8')}" ) # See https://datatracker.ietf.org/doc/html/rfc4253#section-6.6 @@ -500,13 +494,13 @@ class OpensshCertificate: @classmethod def load(cls, path): if not os.path.exists(path): - raise ValueError("%s is not a valid path." % path) + raise ValueError(f"{path} is not a valid path.") try: with open(path, "rb") as cert_file: data = cert_file.read() except (IOError, OSError) as e: - raise ValueError("%s cannot be opened for reading: %s" % (path, e)) + raise ValueError(f"{path} cannot be opened for reading: {e}") try: format_identifier, b64_cert = data.split(b" ")[:2] @@ -520,7 +514,7 @@ class OpensshCertificate: break else: raise ValueError( - "Invalid certificate format identifier: %s" % format_identifier + f"Invalid certificate format identifier: {format_identifier}" ) parser = OpensshParser(cert) @@ -532,12 +526,11 @@ class OpensshCertificate: cert_info = cls._parse_cert_info(pub_key_type, parser) signature = parser.string() except (TypeError, ValueError) as e: - raise ValueError("Invalid certificate data: %s" % e) + raise ValueError(f"Invalid certificate data: {e}") if parser.remaining_bytes(): raise ValueError( - "%s bytes of additional data was not parsed while loading %s" - % (parser.remaining_bytes(), path) + f"{parser.remaining_bytes()} bytes of additional data was not parsed while loading {path}" ) return cls( @@ -651,7 +644,7 @@ class OpensshCertificate: def apply_directives(directives): if any(d not in _DIRECTIVES for d in directives): - raise ValueError("directives must be one of %s" % ", ".join(_DIRECTIVES)) + raise ValueError(f"directives must be one of {', '.join(_DIRECTIVES)}") directive_to_option = { "no-x11-forwarding": OpensshCertificateOption( @@ -696,7 +689,7 @@ def get_cert_info_object(key_type): elif key_type == "ed25519": cert_info = OpensshED25519CertificateInfo() else: - raise ValueError("%s is not a valid key type" % key_type) + raise ValueError(f"{key_type} is not a valid key type") return cert_info @@ -708,8 +701,8 @@ def get_option_type(name): result = "extension" else: raise ValueError( - "%s is not a valid option. " % name - + "Custom options must start with 'critical:' or 'extension:' to indicate type" + f"{name} is not a valid option. " + "Custom options must start with 'critical:' or 'extension:' to indicate type" ) return result diff --git a/plugins/module_utils/openssh/cryptography.py b/plugins/module_utils/openssh/cryptography.py index 4460f4ca..7dda132b 100644 --- a/plugins/module_utils/openssh/cryptography.py +++ b/plugins/module_utils/openssh/cryptography.py @@ -137,8 +137,7 @@ class AsymmetricKeypair: if keytype not in _ALGORITHM_PARAMETERS.keys(): raise InvalidKeyTypeError( - "%s is not a valid keytype. Valid keytypes are %s" - % (keytype, ", ".join(_ALGORITHM_PARAMETERS.keys())) + f"{keytype} is not a valid keytype. Valid keytypes are {', '.join(_ALGORITHM_PARAMETERS)}" ) if not size: @@ -146,7 +145,7 @@ class AsymmetricKeypair: else: if size not in _ALGORITHM_PARAMETERS[keytype]["valid_sizes"]: raise InvalidKeySizeError( - "%s is not a valid key size for %s keys" % (size, keytype) + f"{size} is not a valid key size for {keytype} keys" ) if passphrase: @@ -229,9 +228,7 @@ class AsymmetricKeypair: elif isinstance(privatekey, Ed25519PrivateKey): keytype = "ed25519" else: - raise InvalidKeyTypeError( - "Key type '%s' is not supported" % type(privatekey) - ) + raise InvalidKeyTypeError(f"Key type '{type(privatekey)}' is not supported") return cls( keytype=keytype, @@ -363,7 +360,7 @@ class OpensshKeypair: """ if comment is None: - comment = "%s@%s" % (getuser(), gethostname()) + comment = f"{getuser()}@{gethostname()}" asym_keypair = AsymmetricKeypair.generate(keytype, size, passphrase) openssh_privatekey = cls.encode_openssh_privatekey(asym_keypair, "SSH") @@ -457,7 +454,7 @@ class OpensshKeypair: validate_comment(comment) encoded_publickey += ( - (" %s" % comment).encode(encoding=_TEXT_ENCODING) if comment else b"" + f" {comment}".encode(encoding=_TEXT_ENCODING) if comment else b"" ) return encoded_publickey @@ -541,7 +538,7 @@ class OpensshKeypair: self.__comment = comment encoded_comment = ( - (" %s" % self.__comment).encode(encoding=_TEXT_ENCODING) + f" {self.__comment}".encode(encoding=_TEXT_ENCODING) if self.__comment else b"" ) @@ -578,12 +575,11 @@ def load_privatekey(path, passphrase, key_format): privatekey_loader = privatekey_loaders[key_format] except KeyError: raise InvalidKeyFormatError( - "%s is not a valid key format (%s)" - % (key_format, ",".join(privatekey_loaders.keys())) + f"{key_format} is not a valid key format ({','.join(privatekey_loaders)})" ) if not os.path.exists(path): - raise InvalidPrivateKeyFileError("No file was found at %s" % path) + raise InvalidPrivateKeyFileError(f"No file was found at {path}") try: with open(path, "rb") as f: @@ -631,12 +627,11 @@ def load_publickey(path, key_format): publickey_loader = publickey_loaders[key_format] except KeyError: raise InvalidKeyFormatError( - "%s is not a valid key format (%s)" - % (key_format, ",".join(publickey_loaders.keys())) + f"{key_format} is not a valid key format ({','.join(publickey_loaders)})" ) if not os.path.exists(path): - raise InvalidPublicKeyFileError("No file was found at %s" % path) + raise InvalidPublicKeyFileError(f"No file was found at {path}") try: with open(path, "rb") as f: @@ -689,13 +684,13 @@ def get_encryption_algorithm(passphrase): def validate_comment(comment): if not hasattr(comment, "encode"): - raise InvalidCommentError("%s cannot be encoded to text" % comment) + raise InvalidCommentError(f"{comment} cannot be encoded to text") def extract_comment(path): if not os.path.exists(path): - raise InvalidPublicKeyFileError("No file was found at %s" % path) + raise InvalidPublicKeyFileError(f"No file was found at {path}") try: with open(path, "rb") as f: @@ -715,6 +710,5 @@ def calculate_fingerprint(openssh_publickey): decoded_pubkey = b64decode(openssh_publickey.split(b" ")[1]) digest.update(decoded_pubkey) - return "SHA256:%s" % b64encode(digest.finalize()).decode( - encoding=_TEXT_ENCODING - ).rstrip("=") + value = b64encode(digest.finalize()).decode(encoding=_TEXT_ENCODING).rstrip("=") + return f"SHA256:{value}" diff --git a/plugins/module_utils/openssh/utils.py b/plugins/module_utils/openssh/utils.py index 57c9e56e..63d45710 100644 --- a/plugins/module_utils/openssh/utils.py +++ b/plugins/module_utils/openssh/utils.py @@ -91,7 +91,7 @@ class OpensshParser: def __init__(self, data): if not isinstance(data, (bytes, bytearray)): - raise TypeError("Data must be bytes-like not %s" % type(data)) + raise TypeError(f"Data must be bytes-like not {type(data)}") self._data = memoryview(data) if PY3 else data self._pos = 0 @@ -174,7 +174,7 @@ class OpensshParser: def _check_position(self, offset): if self._pos + offset > len(self._data): - raise ValueError("Insufficient data remaining at position: %s" % self._pos) + raise ValueError(f"Insufficient data remaining at position: {self._pos}") elif self._pos + offset < 0: raise ValueError("Position cannot be less than zero.") else: @@ -210,7 +210,7 @@ class OpensshParser: signature_data["R"] = cls._big_int(signature_blob[:32], "little") signature_data["S"] = cls._big_int(signature_blob[32:], "little") else: - raise ValueError("%s is not a valid signature type" % signature_type) + raise ValueError(f"{signature_type} is not a valid signature type") signature_data["signature_type"] = signature_type @@ -220,7 +220,7 @@ class OpensshParser: def _big_int(cls, raw_string, byte_order, signed=False): if byte_order not in ("big", "little"): raise ValueError( - "Byte_order must be one of (big, little) not %s" % byte_order + f"Byte_order must be one of (big, little) not {byte_order}" ) if PY3: @@ -279,7 +279,7 @@ class _OpensshWriter: if buffer is not None: if not isinstance(buffer, (bytes, bytearray)): raise TypeError( - "Buffer must be a bytes-like object not %s" % type(buffer) + f"Buffer must be a bytes-like object not {type(buffer)}" ) else: buffer = bytearray() @@ -288,7 +288,7 @@ class _OpensshWriter: def boolean(self, value): if not isinstance(value, bool): - raise TypeError("Value must be of type bool not %s" % type(value)) + raise TypeError(f"Value must be of type bool not {type(value)}") self._buff.extend(_BOOLEAN.pack(value)) @@ -296,10 +296,10 @@ class _OpensshWriter: def uint32(self, value): if not isinstance(value, int): - raise TypeError("Value must be of type int not %s" % type(value)) + raise TypeError(f"Value must be of type int not {type(value)}") if value < 0 or value > _UINT32_MAX: raise ValueError( - "Value must be a positive integer less than %s" % _UINT32_MAX + f"Value must be a positive integer less than {_UINT32_MAX}" ) self._buff.extend(_UINT32.pack(value)) @@ -308,10 +308,10 @@ class _OpensshWriter: def uint64(self, value): if not isinstance(value, (long, int)): - raise TypeError("Value must be of type (long, int) not %s" % type(value)) + raise TypeError(f"Value must be of type (long, int) not {type(value)}") if value < 0 or value > _UINT64_MAX: raise ValueError( - "Value must be a positive integer less than %s" % _UINT64_MAX + f"Value must be a positive integer less than {_UINT64_MAX}" ) self._buff.extend(_UINT64.pack(value)) @@ -320,7 +320,7 @@ class _OpensshWriter: def string(self, value): if not isinstance(value, (bytes, bytearray)): - raise TypeError("Value must be bytes-like not %s" % type(value)) + raise TypeError(f"Value must be bytes-like not {type(value)}") self.uint32(len(value)) self._buff.extend(value) @@ -328,7 +328,7 @@ class _OpensshWriter: def mpint(self, value): if not isinstance(value, (int, long)): - raise TypeError("Value must be of type (long, int) not %s" % type(value)) + raise TypeError(f"Value must be of type (long, int) not {type(value)}") self.string(self._int_to_mpint(value)) @@ -336,18 +336,18 @@ class _OpensshWriter: def name_list(self, value): if not isinstance(value, list): - raise TypeError("Value must be a list of byte strings not %s" % type(value)) + raise TypeError(f"Value must be a list of byte strings not {type(value)}") try: self.string(",".join(value).encode("ASCII")) except UnicodeEncodeError as e: - raise ValueError("Name-list's must consist of US-ASCII characters: %s" % e) + raise ValueError(f"Name-list's must consist of US-ASCII characters: {e}") return self def string_list(self, value): if not isinstance(value, list): - raise TypeError("Value must be a list of byte string not %s" % type(value)) + raise TypeError(f"Value must be a list of byte string not {type(value)}") writer = _OpensshWriter() for s in value: diff --git a/plugins/module_utils/serial.py b/plugins/module_utils/serial.py index a3d280aa..875b6544 100644 --- a/plugins/module_utils/serial.py +++ b/plugins/module_utils/serial.py @@ -37,9 +37,7 @@ def parse_serial(value): raise ValueError("the value is not in range [0, 255]") except ValueError as exc: raise ValueError( - "The {idx}{th} part {part!r} is not a hexadecimal number in range [0, 255]: {exc}".format( - idx=i + 1, th=th(i + 1), part=part, exc=exc - ) + f"The {i + 1}{th(i + 1)} part {part!r} is not a hexadecimal number in range [0, 255]: {exc}" ) result = (result << 8) | part_value return result diff --git a/plugins/module_utils/time.py b/plugins/module_utils/time.py index 0b4f5fb5..18d1c48b 100644 --- a/plugins/module_utils/time.py +++ b/plugins/module_utils/time.py @@ -146,7 +146,7 @@ def get_relative_time_option( result = to_native(input_string) if result is None: raise OpenSSLObjectError( - 'The timespec "%s" for %s is not valid' % input_string, input_name + f'The timespec "{input_string}" for {input_name} is not valid' ) # Relative time if result.startswith("+") or result.startswith("-"): @@ -179,5 +179,5 @@ def get_relative_time_option( return add_or_remove_timezone(res, with_timezone=with_timezone) raise OpenSSLObjectError( - 'The time spec "%s" for %s is invalid' % (input_string, input_name) + f'The time spec "{input_string}" for {input_name} is invalid' ) diff --git a/plugins/modules/acme_account.py b/plugins/modules/acme_account.py index 50c697cc..a846c812 100644 --- a/plugins/modules/acme_account.py +++ b/plugins/modules/acme_account.py @@ -229,8 +229,7 @@ def main(): base64.urlsafe_b64decode(key) except Exception as e: module.fail_json( - msg="Key for external_account_binding must be Base64 URL encoded (%s)" - % e + msg=f"Key for external_account_binding must be Base64 URL encoded ({e})" ) module.params["external_account_binding"]["key"] = key @@ -296,7 +295,7 @@ def main(): ) except KeyParsingError as e: raise ModuleFailException( - "Error while parsing new account key: {msg}".format(msg=e.msg) + f"Error while parsing new account key: {e.msg}" ) # Verify that the account exists and has not been deactivated created, account_data = account.setup_account(allow_creation=False) diff --git a/plugins/modules/acme_account_info.py b/plugins/modules/acme_account_info.py index a55b966f..bf47cf0e 100644 --- a/plugins/modules/acme_account_info.py +++ b/plugins/modules/acme_account_info.py @@ -233,9 +233,7 @@ def get_orders_list(module, client, orders_url): if not res.get("orders"): if orders: module.warn( - "When retrieving orders list part {0}, got empty result list".format( - orders_url - ) + f"When retrieving orders list part {orders_url}, got empty result list" ) break # Add order URLs to result list diff --git a/plugins/modules/acme_certificate.py b/plugins/modules/acme_certificate.py index a107122a..68d3503b 100644 --- a/plugins/modules/acme_certificate.py +++ b/plugins/modules/acme_certificate.py @@ -643,9 +643,7 @@ class ACMECertificateClient: ) except ValueError as exc: self.module.warn( - "Error while parsing criterium: {error}. Ignoring criterium.".format( - error=exc - ) + f"Error while parsing criterium: {exc}. Ignoring criterium." ) if self.profile is not None: @@ -654,9 +652,7 @@ class ACMECertificateClient: raise ModuleFailException(msg="The ACME CA does not support profiles.") if self.profile not in meta_profiles: raise ModuleFailException( - msg="The ACME CA does not support selected profile {0!r}.".format( - self.profile - ) + msg=f"The ACME CA does not support selected profile {self.profile!r}." ) # Make sure account exists @@ -678,7 +674,7 @@ class ACMECertificateClient: self.changed = created or updated if self.csr is not None and not os.path.exists(self.csr): - raise ModuleFailException("CSR %s not found" % (self.csr)) + raise ModuleFailException(f"CSR {self.csr} not found") # Extract list of identifiers from CSR self.identifiers = self.client.backend.get_ordered_csr_identifiers( @@ -758,9 +754,7 @@ class ACMECertificateClient: and self.challenge not in data[authz.identifier] ): raise ModuleFailException( - "Found no challenge of type '{0}' for identifier {1}!".format( - self.challenge, type_identifier - ) + f"Found no challenge of type '{self.challenge}' for identifier {type_identifier}!" ) # Get DNS challenge data data_dns = {} @@ -812,9 +806,7 @@ class ACMECertificateClient: alt_cert = CertificateChain.download(self.client, alternate) except ModuleFailException as e: self.module.warn( - "Error while downloading alternative certificate {0}: {1}".format( - alternate, e - ) + f"Error while downloading alternative certificate {alternate}: {e}" ) continue alternate_chains.append(alt_cert) @@ -825,7 +817,7 @@ class ACMECertificateClient: for chain in chains: if matcher.match(chain): self.module.debug( - "Found matching chain for criterium {0}".format(criterium_idx) + f"Found matching chain for criterium {criterium_idx}" ) return chain return None @@ -844,13 +836,11 @@ class ACMECertificateClient: ) if authz is None: raise ModuleFailException( - 'Found no authorization information for "{identifier}"!'.format( - identifier=combine_identifier(identifier_type, identifier) - ) + f'Found no authorization information for "{combine_identifier(identifier_type, identifier)}"!' ) if authz.status != "valid": authz.raise_error( - 'Status is "{status}" and not "valid"'.format(status=authz.status), + f'Status is "{authz.status}" and not "valid"', module=self.module, ) @@ -911,7 +901,7 @@ class ACMECertificateClient: pass if authz.status != "deactivated": self.module.warn( - warning="Could not deactivate authz object {0}.".format(authz.url) + warning=f"Could not deactivate authz object {authz.url}." ) diff --git a/plugins/modules/acme_certificate_deactivate_authz.py b/plugins/modules/acme_certificate_deactivate_authz.py index c3a95988..77fc26f3 100644 --- a/plugins/modules/acme_certificate_deactivate_authz.py +++ b/plugins/modules/acme_certificate_deactivate_authz.py @@ -98,9 +98,7 @@ def main(): # ignore errors pass if authz.status != "deactivated": - module.warn( - warning="Could not deactivate authz object {0}.".format(authz.url) - ) + module.warn(warning=f"Could not deactivate authz object {authz.url}.") module.exit_json(changed=changed) except ModuleFailException as e: diff --git a/plugins/modules/acme_certificate_order_create.py b/plugins/modules/acme_certificate_order_create.py index 73c7cf66..3193c80f 100644 --- a/plugins/modules/acme_certificate_order_create.py +++ b/plugins/modules/acme_certificate_order_create.py @@ -414,9 +414,7 @@ def main(): ) if profile not in meta_profiles: raise ModuleFailException( - msg="The ACME CA does not support selected profile {0!r}.".format( - profile - ) + msg=f"The ACME CA does not support selected profile {profile!r}." ) order = None diff --git a/plugins/modules/acme_certificate_order_validate.py b/plugins/modules/acme_certificate_order_validate.py index 5ef374b8..22b07704 100644 --- a/plugins/modules/acme_certificate_order_validate.py +++ b/plugins/modules/acme_certificate_order_validate.py @@ -271,13 +271,10 @@ def main(): missing_challenge_authzs = [k for k, v in challenges.items() if v is None] if missing_challenge_authzs: + missing_challenge_authzs = ", ".join(sorted(missing_challenge_authzs)) raise ModuleFailException( "The challenge parameter must be supplied if there are pending authorizations." - " The following authorizations are pending: {missing_challenge_authzs}".format( - missing_challenge_authzs=", ".join( - sorted(missing_challenge_authzs) - ), - ) + f" The following authorizations are pending: {missing_challenge_authzs}" ) bad_challenge_authzs = [ @@ -286,18 +283,15 @@ def main(): if authz.find_challenge(challenges[authz.combined_identifier]) is None ] if bad_challenge_authzs: - raise ModuleFailException( - "The following authorizations do not support the selected challenges: {authz_challenges_pairs}".format( - authz_challenges_pairs=", ".join( - sorted( - "{authz} with {challenge}".format( - authz=authz, challenge=challenges[authz] - ) - for authz in bad_challenge_authzs - ) - ), + authz_challenges_pairs = ", ".join( + sorted( + f"{authz} with {challenges[authz]}" + for authz in bad_challenge_authzs ) ) + raise ModuleFailException( + f"The following authorizations do not support the selected challenges: {authz_challenges_pairs}" + ) really_pending_authzs = [ authz diff --git a/plugins/modules/acme_certificate_renewal_info.py b/plugins/modules/acme_certificate_renewal_info.py index 2bc645ac..fc46f2f5 100644 --- a/plugins/modules/acme_certificate_renewal_info.py +++ b/plugins/modules/acme_certificate_renewal_info.py @@ -231,7 +231,7 @@ def main(): ) except ModuleFailException as e: if module.params["treat_parsing_error_as_non_existing"]: - complete(True, msg="Certificate cannot be parsed: {0}".format(e.msg)) + complete(True, msg=f"Certificate cannot be parsed: {e.msg}") e.do_fail(module) result["parsable"] = True @@ -265,24 +265,18 @@ def main(): ) msg_append = "" if "explanationURL" in renewal_info: - msg_append = ". Information on renewal interval: {0}".format( - renewal_info["explanationURL"] - ) + msg_append = f". Information on renewal interval: {renewal_info['explanationURL']}" result["supports_ari"] = True if now > window_end: complete( True, - msg="The suggested renewal interval provided by ARI is in the past{0}".format( - msg_append - ), + msg=f"The suggested renewal interval provided by ARI is in the past{msg_append}", ) if module.params["ari_algorithm"] == "start": if now > window_start: complete( True, - msg="The suggested renewal interval provided by ARI has begun{0}".format( - msg_append - ), + msg=f"The suggested renewal interval provided by ARI has begun{msg_append}", ) else: random_time = backend.interpolate_timestamp( @@ -291,10 +285,7 @@ def main(): if now > random_time: complete( True, - msg="The picked random renewal time {0} in sugested renewal internal provided by ARI is in the past{1}".format( - random_time, - msg_append, - ), + msg=f"The picked random renewal time {random_time} in sugested renewal internal provided by ARI is in the past{msg_append}", ) if module.params["remaining_days"] is not None: @@ -302,7 +293,7 @@ def main(): if remaining_days < module.params["remaining_days"]: complete( True, - msg="The certificate expires in {0} days".format(remaining_days), + msg=f"The certificate expires in {remaining_days} days", ) if module.params["remaining_percentage"] is not None: @@ -314,10 +305,8 @@ def main(): if timestamp < now: complete( True, - msg="The remaining percentage {0}% of the certificate's lifespan was reached on {1}".format( - module.params["remaining_percentage"] * 100, - timestamp, - ), + msg=f"The remaining percentage {module.params['remaining_percentage'] * 100}%" + f" of the certificate's lifespan was reached on {timestamp}", ) complete(False) diff --git a/plugins/modules/acme_certificate_revoke.py b/plugins/modules/acme_certificate_revoke.py index 600acba4..5f9d729e 100644 --- a/plugins/modules/acme_certificate_revoke.py +++ b/plugins/modules/acme_certificate_revoke.py @@ -182,9 +182,7 @@ def main(): private_key, private_key_content, passphrase=passphrase ) except KeyParsingError as e: - raise ModuleFailException( - "Error while parsing private key: {msg}".format(msg=e.msg) - ) + raise ModuleFailException(f"Error while parsing private key: {e.msg}") # Step 2: sign revokation request with private key jws_header = { "alg": private_key_data["alg"], diff --git a/plugins/modules/acme_challenge_cert_helper.py b/plugins/modules/acme_challenge_cert_helper.py index 6ad7ad46..66ee3c04 100644 --- a/plugins/modules/acme_challenge_cert_helper.py +++ b/plugins/modules/acme_challenge_cert_helper.py @@ -259,7 +259,7 @@ def main(): ) ) except Exception as e: - raise ModuleFailException("Error while loading private key: {0}".format(e)) + raise ModuleFailException(f"Error while loading private key: {e}") # Some common attributes domain = to_text(challenge_data["resource"]) @@ -276,7 +276,7 @@ def main(): san = cryptography.x509.IPAddress(ipaddress.ip_address(identifier)) else: raise ModuleFailException( - 'Unsupported identifier type "{0}"'.format(identifier_type) + f'Unsupported identifier type "{identifier_type}"' ) # Generate regular self-signed certificate diff --git a/plugins/modules/certificate_complete_chain.py b/plugins/modules/certificate_complete_chain.py index 86da1a89..665db3c9 100644 --- a/plugins/modules/certificate_complete_chain.py +++ b/plugins/modules/certificate_complete_chain.py @@ -212,18 +212,16 @@ def is_parent(module, cert, potential_parent): public_key.verify(cert.cert.signature, cert.cert.tbs_certificate_bytes) else: # Unknown public key type - module.warn('Unknown public key type "{0}"'.format(public_key)) + module.warn(f'Unknown public key type "{public_key}"') return False return True except cryptography.exceptions.InvalidSignature: return False except cryptography.exceptions.UnsupportedAlgorithm: - module.warn( - 'Unsupported algorithm "{0}"'.format(cert.cert.signature_hash_algorithm) - ) + module.warn(f'Unsupported algorithm "{cert.cert.signature_hash_algorithm}"') return False except Exception as e: - module.fail_json(msg="Unknown error on signature validation: {0}".format(e)) + module.fail_json(msg=f"Unknown error on signature validation: {e}") def parse_PEM_list(module, text, source, fail_on_error=True): @@ -239,9 +237,7 @@ def parse_PEM_list(module, text, source, fail_on_error=True): ) result.append(Certificate(cert_pem, cert)) except Exception as e: - msg = "Cannot parse certificate #{0} from {1}: {2}".format( - len(result) + 1, source, e - ) + msg = f"Cannot parse certificate #{len(result) + 1} from {source}: {e}" if fail_on_error: module.fail_json(msg=msg) else: @@ -262,7 +258,7 @@ def load_PEM_list(module, path, fail_on_error=True): fail_on_error=fail_on_error, ) except Exception as e: - msg = "Cannot read certificate file {0}: {1}".format(path, e) + msg = f"Cannot read certificate file {path}: {e}" if fail_on_error: module.fail_json(msg=msg) else: @@ -357,9 +353,9 @@ def main(): if not is_parent(module, chain[i - 1], parent): module.fail_json( msg=( - "Cannot verify input chain: certificate #{2}: {3} is not issuer " - + "of certificate #{0}: {1}" - ).format(i, format_cert(chain[i - 1]), i + 1, format_cert(parent)) + f"Cannot verify input chain: certificate #{i + 1}: {format_cert(parent)} is not issuer " + f"of certificate #{i}: {format_cert(chain[i - 1])}" + ) ) # Load intermediate certificates @@ -392,9 +388,7 @@ def main(): current = intermediate else: module.fail_json( - msg="Cannot complete chain. Stuck at certificate {0}".format( - format_cert(current) - ) + msg=f"Cannot complete chain. Stuck at certificate {format_cert(current)}" ) # Return results diff --git a/plugins/modules/ecs_certificate.py b/plugins/modules/ecs_certificate.py index 9424721e..174fbfa2 100644 --- a/plugins/modules/ecs_certificate.py +++ b/plugins/modules/ecs_certificate.py @@ -665,16 +665,12 @@ class EcsCertificate: ], ) except SessionConfigurationException as e: - module.fail_json( - msg="Failed to initialize Entrust Provider: {0}".format(to_native(e)) - ) + module.fail_json(msg=f"Failed to initialize Entrust Provider: {e}") try: self.ecs_client.GetAppVersion() except RestOperationException as e: module.fail_json( - msg="Please verify credential information. Received exception when testing ECS connection: {0}".format( - to_native(e.message) - ) + msg=f"Please verify credential information. Received exception when testing ECS connection: {e.message}" ) # Conversion of the fields that go into the 'tracking' parameter of the request object @@ -744,7 +740,7 @@ class EcsCertificate: try: # Use serial_number to identify if certificate is an Entrust Certificate # with an associated tracking ID - serial_number = "{0:X}".format(self.cert.serial_number) + serial_number = f"{self.cert.serial_number:X}" cert_results = self.ecs_client.GetCertificates( serialNumber=serial_number ).get("certificates", {}) @@ -764,9 +760,7 @@ class EcsCertificate: self.cert_days = calculate_cert_days(self.cert_details.get("expiresAfter")) except RestOperationException as e: module.fail_json( - 'Failed to get details of certificate with tracking_id="{0}", Error: '.format( - self.tracking_id - ), + f'Failed to get details of certificate with tracking_id="{self.tracking_id}", Error: ', to_native(e.message), ) @@ -782,10 +776,9 @@ class EcsCertificate: and module.params["tracking_id"] != self.tracking_id ): module.warn( - 'tracking_id parameter of "{0}" provided, but will be ignored. Valid certificate was present in path "{1}" with ' - 'tracking_id of "{2}".'.format( - module.params["tracking_id"], self.path, self.tracking_id - ) + f'tracking_id parameter of "{module.params["tracking_id"]}" provided, but will be ignored.' + f' Valid certificate was present in path "{self.path}" with ' + f'tracking_id of "{self.tracking_id}".' ) # If we did not end up setting tracking_id based on existing cert, get from module params @@ -822,10 +815,10 @@ class EcsCertificate: # We will be performing a reissue operation. if self.request_type != "new" and not self.tracking_id: module.warn( - 'No existing Entrust certificate found in path={0} and no tracking_id was provided, setting request_type to "new" for this task' - "run. Future playbook runs that point to the pathination file in {1} will use request_type={2}".format( - self.path, self.path, self.request_type - ) + f"No existing Entrust certificate found in path={self.path}" + ' and no tracking_id was provided, setting request_type to "new" for this task' + "run. Future playbook runs that point to the pathination file" + f" in {self.path} will use request_type={self.request_type}" ) self.request_type = "new" elif self.request_type == "new" and self.tracking_id: @@ -860,9 +853,7 @@ class EcsCertificate: self.set_cert_details(module) except RestOperationException as e: module.fail_json( - msg="Failed to request new certificate from Entrust (ECS) {0}".format( - e.message - ) + msg=f"Failed to request new certificate from Entrust (ECS) {e.message}" ) if self.request_type != "validate_only": @@ -1020,9 +1011,7 @@ def main(): MINIMAL_CRYPTOGRAPHY_VERSION ): module.fail_json( - msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) - ), + msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"), exception=CRYPTOGRAPHY_IMP_ERR, ) @@ -1033,9 +1022,7 @@ def main(): or module.params["request_type"] == "validate_only" ): module.fail_json( - msg='The tracking_id field is invalid when request_type="{0}".'.format( - module.params["request_type"] - ) + msg=f'The tracking_id field is invalid when request_type="{module.params["request_type"]}".' ) # A reissued request can not specify an expiration date or lifetime @@ -1053,15 +1040,12 @@ def main(): module_params_csr = module.params["csr"] if module_params_csr is None: module.fail_json( - msg="The csr field is required when request_type={0}".format( - module.params["request_type"] - ) + msg=f"The csr field is required when request_type={module.params['request_type']}" ) elif not os.path.exists(module_params_csr): module.fail_json( - msg="The csr field of {0} was not a valid path. csr is required when request_type={1}".format( - module_params_csr, module.params["request_type"] - ) + msg=f"The csr field of {module_params_csr} was not a valid path." + f" csr is required when request_type={module.params['request_type']}" ) if module.params["ou"] and len(module.params["ou"]) > 1: @@ -1088,9 +1072,7 @@ def main(): if module.params["cert_expiry"]: if not validate_cert_expiry(module.params["cert_expiry"]): module.fail_json( - msg='The "cert_expiry" parameter of "{0}" is not a valid date or date-time'.format( - module.params["cert_expiry"] - ) + msg=f'The "cert_expiry" parameter of "{module.params["cert_expiry"]}" is not a valid date or date-time' ) certificate = EcsCertificate(module) diff --git a/plugins/modules/ecs_domain.py b/plugins/modules/ecs_domain.py index 210b243e..be4ab3a7 100644 --- a/plugins/modules/ecs_domain.py +++ b/plugins/modules/ecs_domain.py @@ -275,15 +275,13 @@ class EcsDomain: ) except SessionConfigurationException as e: module.fail_json( - msg="Failed to initialize Entrust Provider: {0}".format(to_native(e)) + msg=f"Failed to initialize Entrust Provider: {to_native(e)}" ) try: self.ecs_client.GetAppVersion() except RestOperationException as e: module.fail_json( - msg="Please verify credential information. Received exception when testing ECS connection: {0}".format( - to_native(e.message) - ) + msg=f"Please verify credential information. Received exception when testing ECS connection: {e.message}" ) def set_domain_details(self, domain_details): @@ -405,9 +403,7 @@ class EcsDomain: self.set_domain_details(result) except RestOperationException as e: module.fail_json( - msg="Failed to request domain validation from Entrust (ECS) {0}".format( - e.message - ) + msg=f"Failed to request domain validation from Entrust (ECS) {e.message}" ) def dump(self): @@ -467,9 +463,7 @@ def main(): and module.params["verification_method"] != "email" ): module.fail_json( - msg='The verification_email field is invalid when verification_method="{0}".'.format( - module.params["verification_method"] - ) + msg=f'The verification_email field is invalid when verification_method="{module.params["verification_method"]}".' ) domain = EcsDomain(module) diff --git a/plugins/modules/get_certificate.py b/plugins/modules/get_certificate.py index b3175cf6..d72486f6 100644 --- a/plugins/modules/get_certificate.py +++ b/plugins/modules/get_certificate.py @@ -369,8 +369,7 @@ def main(): if get_certificate_chain and sys.version_info < (3, 10): module.fail_json( msg="get_certificate_chain=true can only be used with Python 3.10 (Python 3.13+ officially supports this). " - "The Python version used to run the get_certificate module is %s" - % sys.version + f"The Python version used to run the get_certificate module is {sys.version}" ) backend = module.params.get("select_crypto_backend") @@ -388,16 +387,14 @@ def main(): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library " "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) @@ -437,14 +434,12 @@ def main(): # Note: get_server_certificate does not support SNI! cert = get_server_certificate((host, port), ca_certs=ca_cert) except Exception as e: - module.fail_json( - msg="Failed to get cert from {0}:{1}, error: {2}".format(host, port, e) - ) + module.fail_json(msg=f"Failed to get cert from {host}:{port}, error: {e}") else: # Python >= 2.7.9 try: if proxy_host: - connect = "CONNECT %s:%s HTTP/1.0\r\n\r\n" % (host, port) + connect = f"CONNECT {host}:{port} HTTP/1.0\r\n\r\n" sock = socket() atexit.register(sock.close) sock.connect((proxy_host, proxy_port)) @@ -489,9 +484,7 @@ def main(): # If tls_ctx_option_attr is not an integer else: module.fail_json( - msg="Failed to determine the numeric value for {0}".format( - tls_ctx_option_str - ) + msg=f"Failed to determine the numeric value for {tls_ctx_option_str}" ) # If the item is an integer elif isinstance(tls_ctx_option, int): @@ -500,9 +493,7 @@ def main(): # If the item is not a string nor integer else: module.fail_json( - msg="tls_ctx_options must be a string or integer, got {0!r}".format( - tls_ctx_option - ) + msg=f"tls_ctx_options must be a string or integer, got {tls_ctx_option!r}" ) tls_ctx_option_int = ( 0 # make pylint happy; this code is actually unreachable @@ -513,9 +504,7 @@ def main(): ctx.options |= tls_ctx_option_int except Exception: module.fail_json( - msg="Failed to add {0} to CTX options".format( - tls_ctx_option_str or tls_ctx_option_int - ) + msg=f"Failed to add {tls_ctx_option_str or tls_ctx_option_int} to CTX options" ) tls_sock = ctx.wrap_socket(sock, server_hostname=server_name or host) @@ -568,15 +557,11 @@ def main(): except Exception as e: if proxy_host: module.fail_json( - msg="Failed to get cert via proxy {0}:{1} from {2}:{3}, error: {4}".format( - proxy_host, proxy_port, host, port, e - ) + msg=f"Failed to get cert via proxy {proxy_host}:{proxy_port} from {host}:{port}, error: {e}" ) else: module.fail_json( - msg="Failed to get cert from {0}:{1}, error: {2}".format( - host, port, e - ) + msg=f"Failed to get cert from {host}:{port}, error: {e}" ) result["cert"] = cert diff --git a/plugins/modules/luks_device.py b/plugins/modules/luks_device.py index 407cea42..e70ba490 100644 --- a/plugins/modules/luks_device.py +++ b/plugins/modules/luks_device.py @@ -493,9 +493,7 @@ class Handler: return b64decode(to_native(passphrase)) except Exception as exc: self._module.fail_json( - "Error while base64-decoding '{parameter_name}': {exc}".format( - parameter_name=parameter_name, exc=exc - ) + f"Error while base64-decoding '{parameter_name}': {exc}" ) def _run_command(self, command, data=None): @@ -531,10 +529,10 @@ class Handler: if result[RETURN_CODE] != 0: raise ValueError( - "Error while generating LUKS name for %s: %s" % (device, result[STDERR]) + f"Error while generating LUKS name for {device}: {result[STDERR]}" ) dev_uuid = result[STDOUT].strip() - return "luks-%s" % dev_uuid + return f"luks-{dev_uuid}" class CryptHandler(Handler): @@ -551,7 +549,7 @@ class CryptHandler(Handler): result = self._run_command([self._lsblk_bin, device, "-nlo", "type,name"]) if result[RETURN_CODE] != 0: raise ValueError( - "Error while obtaining LUKS name for %s: %s" % (device, result[STDERR]) + f"Error while obtaining LUKS name for {device}: {result[STDERR]}" ) for line in result[STDOUT].splitlines(False): @@ -595,9 +593,9 @@ class CryptHandler(Handler): """check if a keyslot is set""" result = self._run_command([self._cryptsetup_bin, "luksDump", device]) if result[RETURN_CODE] != 0: - raise ValueError("Error while dumping LUKS header from %s" % (device,)) - result_luks1 = "Key Slot %d: ENABLED" % (keyslot) in result[STDOUT] - result_luks2 = " %d: luks2" % (keyslot) in result[STDOUT] + raise ValueError(f"Error while dumping LUKS header from {device}") + result_luks1 = f"Key Slot {keyslot}: ENABLED" in result[STDOUT] + result_luks2 = f" {keyslot}: luks2" in result[STDOUT] return result_luks1 or result_luks2 def _add_pbkdf_options(self, options, pbkdf): @@ -657,9 +655,7 @@ class CryptHandler(Handler): result = self._run_command(args, data=passphrase) if result[RETURN_CODE] != 0: - raise ValueError( - "Error while creating LUKS on %s: %s" % (device, result[STDERR]) - ) + raise ValueError(f"Error while creating LUKS on {device}: {result[STDERR]}") def run_luks_open( self, @@ -696,14 +692,13 @@ class CryptHandler(Handler): result = self._run_command(args, data=passphrase) if result[RETURN_CODE] != 0: raise ValueError( - "Error while opening LUKS container on %s: %s" - % (device, result[STDERR]) + f"Error while opening LUKS container on {device}: {result[STDERR]}" ) def run_luks_close(self, name): result = self._run_command([self._cryptsetup_bin, "close", name]) if result[RETURN_CODE] != 0: - raise ValueError("Error while closing LUKS container %s" % (name)) + raise ValueError(f"Error while closing LUKS container {name}") def run_luks_remove(self, device): wipefs_bin = self._module.get_bin_path("wipefs", True) @@ -714,8 +709,7 @@ class CryptHandler(Handler): result = self._run_command([wipefs_bin, "--all", device]) if result[RETURN_CODE] != 0: raise ValueError( - "Error while wiping LUKS container signatures for %s: %s" - % (device, result[STDERR]) + f"Error while wiping LUKS container signatures for {device}: {result[STDERR]}" ) # For LUKS2, sometimes both `cryptsetup erase` and `wipefs` do **not** @@ -725,8 +719,7 @@ class CryptHandler(Handler): wipe_luks_headers(device) except Exception as exc: raise ValueError( - "Error while wiping LUKS container signatures for %s: %s" - % (device, exc) + f"Error while wiping LUKS container signatures for {device}: {exc}" ) def run_luks_add_key( @@ -766,8 +759,7 @@ class CryptHandler(Handler): result = self._run_command(args, data=b"".join(data) or None) if result[RETURN_CODE] != 0: raise ValueError( - "Error while adding new LUKS keyslot to %s: %s" - % (device, result[STDERR]) + f"Error while adding new LUKS keyslot to {device}: {result[STDERR]}" ) def run_luks_remove_key( @@ -779,7 +771,7 @@ class CryptHandler(Handler): if not force_remove_last_key: result = self._run_command([self._cryptsetup_bin, "luksDump", device]) if result[RETURN_CODE] != 0: - raise ValueError("Error while dumping LUKS header from %s" % (device,)) + raise ValueError(f"Error while dumping LUKS header from {device}") keyslot_count = 0 keyslot_area = False keyslot_re = re.compile(r"^Key Slot [0-9]+: ENABLED") @@ -802,9 +794,8 @@ class CryptHandler(Handler): keyslot_area = False if keyslot_count < 2: self._module.fail_json( - msg="LUKS device %s has less than two active keyslots. " - "To be able to remove a key, please set " - "`force_remove_last_key` to `true`." % device + msg=f"LUKS device {device} has less than two active keyslots. " + "To be able to remove a key, please set `force_remove_last_key` to `true`." ) if keyslot is None: @@ -820,7 +811,7 @@ class CryptHandler(Handler): result = self._run_command(args, data=passphrase) if result[RETURN_CODE] != 0: raise ValueError( - "Error while removing LUKS key from %s: %s" % (device, result[STDERR]) + f"Error while removing LUKS key from {device}: {result[STDERR]}" ) def luks_test_key(self, device, keyfile, passphrase, keyslot=None): @@ -859,8 +850,7 @@ class CryptHandler(Handler): return False raise ValueError( - "Error while testing whether keyslot exists on %s: %s" - % (device, result[STDERR]) + f"Error while testing whether keyslot exists on {device}: {result[STDERR]}" ) @@ -921,8 +911,7 @@ class ConditionsHandler(Handler): # the container is already open but with different name: # suspicious. back off self._module.fail_json( - msg="LUKS container is already opened " - "under different name '%s'." % name + msg=f"LUKS container is already opened under different name '{name}'." ) # container is opened and the names match @@ -1069,13 +1058,11 @@ class ConditionsHandler(Handler): if luks_type == "luks1" and not 0 <= self._module.params[param] <= 7: self._module.fail_json( - msg="%s must be between 0 and 7 when using LUKS1." - % self._module.params[param] + msg=f"{self._module.params[param]} must be between 0 and 7 when using LUKS1." ) elif luks_type == "luks2" and not 0 <= self._module.params[param] <= 31: self._module.fail_json( - msg="%s must be between 0 and 31 when using LUKS2." - % self._module.params[param] + msg=f"{self._module.params[param]} must be between 0 and 31 when using LUKS2." ) @@ -1151,7 +1138,7 @@ def run_module(): statinfo = os.stat(module.params["device"]) mode = statinfo.st_mode if not stat.S_ISBLK(mode) and not stat.S_ISCHR(mode): - raise Exception("{0} is not a device".format(module.params["device"])) + raise Exception(f"{module.params['device']} is not a device") except Exception as e: module.fail_json(msg=str(e)) @@ -1202,7 +1189,7 @@ def run_module(): module.params["pbkdf"], ) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") result["changed"] = True if module.check_mode: module.exit_json(**result) @@ -1219,7 +1206,7 @@ def run_module(): try: name = crypt.generate_luks_name(conditions.device) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") if not module.check_mode: try: crypt.run_luks_open( @@ -1235,7 +1222,7 @@ def run_module(): name, ) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") result["name"] = name result["changed"] = True if module.check_mode: @@ -1247,14 +1234,14 @@ def run_module(): try: name = crypt.get_container_name_by_device(conditions.device) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") else: name = module.params["name"] if not module.check_mode: try: crypt.run_luks_close(name) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") result["name"] = name result["changed"] = True if module.check_mode: @@ -1274,7 +1261,7 @@ def run_module(): module.params["pbkdf"], ) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") result["changed"] = True if module.check_mode: module.exit_json(**result) @@ -1292,7 +1279,7 @@ def run_module(): force_remove_last_key=last_key, ) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") result["changed"] = True if module.check_mode: module.exit_json(**result) @@ -1303,7 +1290,7 @@ def run_module(): try: crypt.run_luks_remove(conditions.device) except ValueError as e: - module.fail_json(msg="luks_device error: %s" % e) + module.fail_json(msg=f"luks_device error: {e}") result["changed"] = True if module.check_mode: module.exit_json(**result) diff --git a/plugins/modules/openssh_cert.py b/plugins/modules/openssh_cert.py index 261102db..ec97b3be 100644 --- a/plugins/modules/openssh_cert.py +++ b/plugins/modules/openssh_cert.py @@ -360,7 +360,7 @@ class Certificate(OpensshModule): elif LooseVersion(ssh_version) < LooseVersion("7.6"): self.module.fail_json( msg="Signing with CA key in ssh agent requires ssh 7.6 or newer." - + " Your version is: %s" % ssh_version + + f" Your version is: {ssh_version}" ) def _exists(self): @@ -371,10 +371,8 @@ class Certificate(OpensshModule): self.original_data = OpensshCertificate.load(self.path) except (TypeError, ValueError) as e: if self.regenerate in ("never", "fail"): - self.module.fail_json( - msg="Unable to read existing certificate: %s" % to_native(e) - ) - self.module.warn("Unable to read existing certificate: %s" % to_native(e)) + self.module.fail_json(msg=f"Unable to read existing certificate: {e}") + self.module.warn(f"Unable to read existing certificate: {e}") def _set_time_parameters(self): try: @@ -486,15 +484,13 @@ class Certificate(OpensshModule): self._safe_secure_move([(temp_certificate, self.path)]) except OSError as e: self.module.fail_json( - msg="Unable to write certificate to %s: %s" % (self.path, to_native(e)) + msg=f"Unable to write certificate to {self.path}: {e}" ) try: self.data = OpensshCertificate.load(self.path) except (TypeError, ValueError) as e: - self.module.fail_json( - msg="Unable to read new certificate: %s" % to_native(e) - ) + self.module.fail_json(msg=f"Unable to read new certificate: {e}") def _generate_temp_certificate(self): key_copy = os.path.join(self.module.tmpdir, os.path.basename(self.public_key)) @@ -502,9 +498,7 @@ class Certificate(OpensshModule): try: self.module.preserved_copy(self.public_key, key_copy) except OSError as e: - self.module.fail_json( - msg="Unable to stage temporary key: %s" % to_native(e) - ) + self.module.fail_json(msg=f"Unable to stage temporary key: {e}") self.module.add_cleanup_file(key_copy) self.ssh_keygen.generate_certificate( @@ -535,7 +529,7 @@ class Certificate(OpensshModule): os.remove(self.path) except OSError as e: self.module.fail_json( - msg="Unable to remove existing certificate: %s" % to_native(e) + msg=f"Unable to remove existing certificate: {to_native(e)}" ) @property diff --git a/plugins/modules/openssl_csr.py b/plugins/modules/openssl_csr.py index 8bbe48f1..20f69bb8 100644 --- a/plugins/modules/openssl_csr.py +++ b/plugins/modules/openssl_csr.py @@ -337,8 +337,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory %s does not exist or the file is not a directory" - % base_dir, + msg=f"The directory {base_dir} does not exist or the file is not a directory", ) try: diff --git a/plugins/modules/openssl_csr_info.py b/plugins/modules/openssl_csr_info.py index 573fc54e..4b729b06 100644 --- a/plugins/modules/openssl_csr_info.py +++ b/plugins/modules/openssl_csr_info.py @@ -341,9 +341,7 @@ def main(): with open(module.params["path"], "rb") as f: data = f.read() except (IOError, OSError) as e: - module.fail_json( - msg="Error while reading CSR file from disk: {0}".format(e) - ) + module.fail_json(msg=f"Error while reading CSR file from disk: {e}") backend, module_backend = select_backend( module, module.params["select_crypto_backend"], data, validate_signature=True diff --git a/plugins/modules/openssl_dhparam.py b/plugins/modules/openssl_dhparam.py index a9076536..e1a8cba9 100644 --- a/plugins/modules/openssl_dhparam.py +++ b/plugins/modules/openssl_dhparam.py @@ -285,7 +285,7 @@ class DHParameterOpenSSL(DHParameterBase): try: module.atomic_move(os.path.abspath(tmpsrc), os.path.abspath(self.path)) except Exception as e: - module.fail_json(msg="Failed to write to file %s: %s" % (self.path, str(e))) + module.fail_json(msg=f"Failed to write to file {self.path}: {str(e)}") def _check_params_valid(self, module): """Check if the params are in the correct state""" @@ -381,8 +381,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory '%s' does not exist or the file is not a directory" - % base_dir, + msg=f"The directory '{base_dir}' does not exist or the file is not a directory", ) if module.params["state"] == "present": @@ -405,9 +404,9 @@ def main(): if backend == "auto": module.fail_json( msg=( - "Cannot detect either the required Python library cryptography (>= {0}) " + f"Cannot detect either the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION}) " "or the OpenSSL binary openssl" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + ) ) if backend == "openssl": @@ -416,7 +415,7 @@ def main(): if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) diff --git a/plugins/modules/openssl_pkcs12.py b/plugins/modules/openssl_pkcs12.py index 59c00d28..794a2da2 100644 --- a/plugins/modules/openssl_pkcs12.py +++ b/plugins/modules/openssl_pkcs12.py @@ -737,24 +737,20 @@ def select_backend(module, backend): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library cryptography (>= {0})" - ).format( - MINIMAL_CRYPTOGRAPHY_VERSION, - ) + msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) return backend, PkcsCryptography(module) else: - raise ValueError("Unsupported value for backend: {0}".format(backend)) + raise ValueError(f"Unsupported value for backend: {backend}") def main(): @@ -812,8 +808,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory '%s' does not exist or the path is not a directory" - % base_dir, + msg=f"The directory '{base_dir}' does not exist or the path is not a directory", ) try: @@ -862,7 +857,7 @@ def main(): result = pkcs12.dump() result["changed"] = changed if os.path.exists(module.params["path"]): - file_mode = "%04o" % stat.S_IMODE(os.stat(module.params["path"]).st_mode) + file_mode = f"{stat.S_IMODE(os.stat(module.params['path']).st_mode):04o}" result["mode"] = file_mode module.exit_json(**result) diff --git a/plugins/modules/openssl_privatekey.py b/plugins/modules/openssl_privatekey.py index a2c23adb..c87b38a4 100644 --- a/plugins/modules/openssl_privatekey.py +++ b/plugins/modules/openssl_privatekey.py @@ -268,8 +268,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory %s does not exist or the file is not a directory" - % base_dir, + msg=f"The directory {base_dir} does not exist or the file is not a directory", ) backend, module_backend = select_backend( diff --git a/plugins/modules/openssl_privatekey_convert.py b/plugins/modules/openssl_privatekey_convert.py index b7d3deff..a6d1f95c 100644 --- a/plugins/modules/openssl_privatekey_convert.py +++ b/plugins/modules/openssl_privatekey_convert.py @@ -146,8 +146,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory %s does not exist or the file is not a directory" - % base_dir, + msg=f"The directory {base_dir} does not exist or the file is not a directory", ) module_backend = select_backend(module=module) diff --git a/plugins/modules/openssl_privatekey_info.py b/plugins/modules/openssl_privatekey_info.py index ea178d03..1ba178f9 100644 --- a/plugins/modules/openssl_privatekey_info.py +++ b/plugins/modules/openssl_privatekey_info.py @@ -242,8 +242,7 @@ def main(): data = f.read() except (IOError, OSError) as e: module.fail_json( - msg="Error while reading private key file from disk: {0}".format(e), - **result, + msg=f"Error while reading private key file from disk: {e}", **result ) result["can_load_key"] = True diff --git a/plugins/modules/openssl_publickey.py b/plugins/modules/openssl_publickey.py index 119028f8..fa38be35 100644 --- a/plugins/modules/openssl_publickey.py +++ b/plugins/modules/openssl_publickey.py @@ -301,7 +301,7 @@ class PublicKey(OpenSSLObject): if self.privatekey_content is None and not os.path.exists(self.privatekey_path): raise PublicKeyError( - "The private key %s does not exist" % self.privatekey_path + f"The private key {self.privatekey_path} does not exist" ) if not self.check(module, perms_required=False) or self.force: @@ -461,9 +461,7 @@ def main(): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library " "cryptography (>= {0})" - ).format(minimal_cryptography_version) + msg=f"Cannot detect the required Python library cryptography (>= {minimal_cryptography_version})", ) if module.params["format"] == "OpenSSH" and backend != "cryptography": @@ -473,7 +471,7 @@ def main(): if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(minimal_cryptography_version) + f"cryptography >= {minimal_cryptography_version}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) @@ -482,8 +480,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory '%s' does not exist or the file is not a directory" - % base_dir, + msg=f"The directory '{base_dir}' does not exist or the file is not a directory", ) try: diff --git a/plugins/modules/openssl_publickey_info.py b/plugins/modules/openssl_publickey_info.py index aad5b6f6..9dc0ec4f 100644 --- a/plugins/modules/openssl_publickey_info.py +++ b/plugins/modules/openssl_publickey_info.py @@ -190,8 +190,7 @@ def main(): data = f.read() except (IOError, OSError) as e: module.fail_json( - msg="Error while reading public key file from disk: {0}".format(e), - **result, + msg=f"Error while reading public key file from disk: {e}", **result ) backend, module_backend = select_backend( diff --git a/plugins/modules/openssl_signature.py b/plugins/modules/openssl_signature.py index 98a381c7..d950a09e 100644 --- a/plugins/modules/openssl_signature.py +++ b/plugins/modules/openssl_signature.py @@ -230,9 +230,7 @@ class SignatureCryptography(SignatureBase): if signature is None: self.module.fail_json( - msg="Unsupported key type. Your cryptography version is {0}".format( - CRYPTOGRAPHY_VERSION - ) + msg=f"Unsupported key type. Your cryptography version is {CRYPTOGRAPHY_VERSION}" ) result["signature"] = base64.b64encode(signature) @@ -261,7 +259,7 @@ def main(): if not os.path.isfile(module.params["path"]): module.fail_json( name=module.params["path"], - msg="The file {0} does not exist".format(module.params["path"]), + msg=f"The file {module.params['path']} does not exist", ) backend = module.params["select_crypto_backend"] @@ -279,16 +277,14 @@ def main(): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect the required Python library " "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})", ) try: if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) diff --git a/plugins/modules/openssl_signature_info.py b/plugins/modules/openssl_signature_info.py index 86981fa3..f5907aea 100644 --- a/plugins/modules/openssl_signature_info.py +++ b/plugins/modules/openssl_signature_info.py @@ -252,9 +252,7 @@ class SignatureInfoCryptography(SignatureInfoBase): if not verified: self.module.fail_json( - msg="Unsupported key type. Your cryptography version is {0}".format( - CRYPTOGRAPHY_VERSION - ) + msg=f"Unsupported key type. Your cryptography version is {CRYPTOGRAPHY_VERSION}" ) result["valid"] = valid return result @@ -282,7 +280,7 @@ def main(): if not os.path.isfile(module.params["path"]): module.fail_json( name=module.params["path"], - msg="The file {0} does not exist".format(module.params["path"]), + msg=f"The file {module.params['path']} does not exist", ) backend = module.params["select_crypto_backend"] @@ -300,17 +298,14 @@ def main(): # Success? if backend == "auto": module.fail_json( - msg=( - "Cannot detect any of the required Python libraries " - "cryptography (>= {0})" - ).format(MINIMAL_CRYPTOGRAPHY_VERSION) + msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})" ) try: if backend == "cryptography": if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) diff --git a/plugins/modules/x509_certificate.py b/plugins/modules/x509_certificate.py index 63740b9f..cbe25487 100644 --- a/plugins/modules/x509_certificate.py +++ b/plugins/modules/x509_certificate.py @@ -386,8 +386,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory %s does not exist or the file is not a directory" - % base_dir, + msg=f"The directory {base_dir} does not exist or the file is not a directory", ) provider = module.params["provider"] diff --git a/plugins/modules/x509_certificate_convert.py b/plugins/modules/x509_certificate_convert.py index eaf57366..3b2b25c2 100644 --- a/plugins/modules/x509_certificate_convert.py +++ b/plugins/modules/x509_certificate_convert.py @@ -152,16 +152,12 @@ def parse_certificate(input, strict=False): pems = split_pem_list(to_text(input)) if len(pems) > 1 and strict: raise ValueError( - "The input contains {count} PEM objects, expecting only one since strict=true".format( - count=len(pems) - ) + f"The input contains {len(pems)} PEM objects, expecting only one since strict=true" ) pem_header_type, content = extract_pem(pems[0], strict=strict) if strict and pem_header_type not in ("CERTIFICATE", "X509 CERTIFICATE"): raise ValueError( - "type is {type!r}, expecting CERTIFICATE or X509 CERTIFICATE".format( - type=pem_header_type - ) + f"type is {pem_header_type!r}, expecting CERTIFICATE or X509 CERTIFICATE" ) input = base64.b64decode(content) else: @@ -187,18 +183,14 @@ class X509CertificateConvertModule(OpenSSLObject): try: self.input = base64.b64decode(self.input) except Exception as exc: - module.fail_json( - msg="Cannot Base64 decode src_content: {exc}".format(exc=exc) - ) + module.fail_json(msg=f"Cannot Base64 decode src_content: {exc}") else: try: with open(self.src_path, "rb") as f: self.input = f.read() except Exception as exc: module.fail_json( - msg="Failure while reading file {fn}: {exc}".format( - fn=self.src_path, exc=exc - ) + msg=f"Failure while reading file {self.src_path}: {exc}" ) self.format = module.params["format"] @@ -210,7 +202,7 @@ class X509CertificateConvertModule(OpenSSLObject): self.input, strict=self.strict ) except Exception as exc: - module.fail_json(msg="Error while parsing PEM: {exc}".format(exc=exc)) + module.fail_json(msg=f"Error while parsing PEM: {exc}") if module.params["verify_cert_parsable"]: self.verify_cert_parsable(module) @@ -237,16 +229,14 @@ class X509CertificateConvertModule(OpenSSLObject): if not CRYPTOGRAPHY_FOUND: module.fail_json( msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) + f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}" ), exception=CRYPTOGRAPHY_IMP_ERR, ) try: load_der_x509_certificate(self.input, default_backend()) except Exception as exc: - module.fail_json( - msg="Error while parsing certificate: {exc}".format(exc=exc) - ) + module.fail_json(msg=f"Error while parsing certificate: {exc}") def needs_conversion(self): if self.dest_content is None or self.dest_content_format is None: @@ -263,11 +253,9 @@ class X509CertificateConvertModule(OpenSSLObject): if self.format == "der": return self.input data = to_bytes(base64.b64encode(self.input)) - lines = [to_bytes("{0}{1}{2}".format(PEM_START, self.wanted_pem_type, PEM_END))] + lines = [to_bytes(f"{PEM_START}{self.wanted_pem_type}{PEM_END}")] lines += [data[i : i + 64] for i in range(0, len(data), 64)] - lines.append( - to_bytes("{0}{1}{2}\n".format(PEM_END_START, self.wanted_pem_type, PEM_END)) - ) + lines.append(to_bytes(f"{PEM_END_START}{self.wanted_pem_type}{PEM_END}\n")) return b"\n".join(lines) def generate(self, module): @@ -323,8 +311,7 @@ def main(): if not os.path.isdir(base_dir): module.fail_json( name=base_dir, - msg="The directory %s does not exist or the file is not a directory" - % base_dir, + msg=f"The directory {base_dir} does not exist or the file is not a directory", ) try: diff --git a/plugins/modules/x509_certificate_info.py b/plugins/modules/x509_certificate_info.py index d29ea5a9..add2691c 100644 --- a/plugins/modules/x509_certificate_info.py +++ b/plugins/modules/x509_certificate_info.py @@ -431,9 +431,7 @@ def main(): with open(module.params["path"], "rb") as f: data = f.read() except (IOError, OSError) as e: - module.fail_json( - msg="Error while reading certificate file from disk: {0}".format(e) - ) + module.fail_json(msg=f"Error while reading certificate file from disk: {e}") backend, module_backend = select_backend( module, module.params["select_crypto_backend"], data @@ -444,12 +442,10 @@ def main(): for k, v in valid_at.items(): if not isinstance(v, string_types): module.fail_json( - msg="The value for valid_at.{0} must be of type string (got {1})".format( - k, type(v) - ) + msg=f"The value for valid_at.{k} must be of type string (got {type(v)})" ) valid_at[k] = get_relative_time_option( - v, "valid_at.{0}".format(k), with_timezone=CRYPTOGRAPHY_TIMEZONE + v, f"valid_at.{k}", with_timezone=CRYPTOGRAPHY_TIMEZONE ) try: diff --git a/plugins/modules/x509_crl.py b/plugins/modules/x509_crl.py index 0d039992..073626f4 100644 --- a/plugins/modules/x509_crl.py +++ b/plugins/modules/x509_crl.py @@ -560,9 +560,7 @@ class CRL(OpenSSLObject): self.digest = select_message_digest(module.params["digest"]) if self.digest is None: - raise CRLError( - 'The digest "{0}" is not supported'.format(module.params["digest"]) - ) + raise CRLError(f'The digest "{module.params["digest"]}" is not supported') self.module = module @@ -578,7 +576,7 @@ class CRL(OpenSSLObject): "invalidity_date": None, "invalidity_date_critical": False, } - path_prefix = "revoked_certificates[{0}].".format(i) + path_prefix = f"revoked_certificates[{i}]." if rc["path"] is not None or rc["content"] is not None: # Load certificate from file or content try: @@ -591,15 +589,11 @@ class CRL(OpenSSLObject): except OpenSSLObjectError as e: if rc["content"] is not None: module.fail_json( - msg="Cannot parse certificate from {0}content: {1}".format( - path_prefix, to_native(e) - ) + msg=f"Cannot parse certificate from {path_prefix}content: {e}" ) else: module.fail_json( - msg='Cannot read certificate "{1}" from {0}path: {2}'.format( - path_prefix, rc["path"], to_native(e) - ) + msg=f'Cannot read certificate "{rc["path"]}" from {path_prefix}path: {e}' ) else: # Specify serial_number (and potentially issuer) directly @@ -668,23 +662,17 @@ class CRL(OpenSSLObject): return check_type_int(value) except TypeError as exc: self.module.fail_json( - msg="Error while parsing revoked_certificates[{idx}].serial_number as an integer: {exc}".format( - idx=index + 1, - exc=to_native(exc), - ) + msg=f"Error while parsing revoked_certificates[{index + 1}].serial_number as an integer: {exc}" ) if self.serial_numbers_format == "hex-octets": try: return parse_serial(check_type_str(value)) except (TypeError, ValueError) as exc: self.module.fail_json( - msg="Error while parsing revoked_certificates[{idx}].serial_number as an colon-separated hex octet string: {exc}".format( - idx=index + 1, - exc=to_native(exc), - ) + msg=f"Error while parsing revoked_certificates[{index + 1}].serial_number as an colon-separated hex octet string: {exc}" ) raise RuntimeError( - "Unexpected value %s of serial_numbers" % (self.serial_numbers_format,) + f"Unexpected value {self.serial_numbers_format} of serial_numbers" ) def _get_info(self, data): @@ -1026,9 +1014,7 @@ def main(): if not CRYPTOGRAPHY_FOUND: module.fail_json( - msg=missing_required_lib( - "cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION) - ), + msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"), exception=CRYPTOGRAPHY_IMP_ERR, ) diff --git a/plugins/modules/x509_crl_info.py b/plugins/modules/x509_crl_info.py index 32911abc..6eacfb7f 100644 --- a/plugins/modules/x509_crl_info.py +++ b/plugins/modules/x509_crl_info.py @@ -207,18 +207,14 @@ def main(): with open(module.params["path"], "rb") as f: data = f.read() except (IOError, OSError) as e: - module.fail_json( - msg="Error while reading CRL file from disk: {0}".format(e) - ) + module.fail_json(msg=f"Error while reading CRL file from disk: {e}") else: data = module.params["content"].encode("utf-8") if not identify_pem_format(data): try: data = base64.b64decode(module.params["content"]) except (binascii.Error, TypeError) as e: - module.fail_json( - msg="Error while Base64 decoding content: {0}".format(e) - ) + module.fail_json(msg=f"Error while Base64 decoding content: {e}") try: result = get_crl_info( diff --git a/plugins/plugin_utils/action_module.py b/plugins/plugin_utils/action_module.py index 1b0d8f50..da923293 100644 --- a/plugins/plugin_utils/action_module.py +++ b/plugins/plugin_utils/action_module.py @@ -99,9 +99,7 @@ class AnsibleActionModule: # Before ansible-core 2.14.2, deprecations were always for aliases: if "name" in d: self.deprecate( - "Alias '{name}' is deprecated. See the module docs for more information".format( - name=d["name"] - ), + f"Alias '{d['name']}' is deprecated. See the module docs for more information", version=d.get("version"), date=d.get("date"), collection_name=d.get("collection_name"), @@ -116,19 +114,13 @@ class AnsibleActionModule: ) for w in self._validation_result._warnings: - self.warn( - "Both option {option} and its alias {alias} are set.".format( - option=w["option"], alias=w["alias"] - ) - ) + self.warn(f"Both option {w['option']} and its alias {w['alias']} are set.") # Fail for validation errors, even in check mode if error: msg = self._validation_result.errors.msg if isinstance(error, UnsupportedError): - msg = "Unsupported parameters for ({name}) {kind}: {msg}".format( - name=self._name, kind="module", msg=msg - ) + msg = f"Unsupported parameters for ({self._name}) module: {msg}" self.fail_json(msg=msg) @@ -140,7 +132,7 @@ class AnsibleActionModule: if isinstance(warning, string_types): self.__warnings.append(warning) else: - raise TypeError("warn requires a string not a %s" % type(warning)) + raise TypeError(f"warn requires a string not a {type(warning)}") def deprecate(self, msg, version=None, date=None, collection_name=None): if version is not None and date is not None: @@ -161,7 +153,7 @@ class AnsibleActionModule: {"msg": msg, "version": version, "collection_name": collection_name} ) else: - raise TypeError("deprecate requires a string not a %s" % type(msg)) + raise TypeError(f"deprecate requires a string not a {type(msg)}") def _return_formatted(self, kwargs): if "invocation" not in kwargs: diff --git a/plugins/plugin_utils/gnupg.py b/plugins/plugin_utils/gnupg.py index 7cac6210..1ac4cd86 100644 --- a/plugins/plugin_utils/gnupg.py +++ b/plugins/plugin_utils/gnupg.py @@ -44,12 +44,9 @@ class PluginGPGRunner(GPGRunner): stdout = to_native(stdout, errors="surrogate_or_replace") stderr = to_native(stderr, errors="surrogate_or_replace") if check_rc and p.returncode != 0: + stdout_n = (to_native(stdout, errors="surrogate_or_replace"),) + stderr_n = (to_native(stderr, errors="surrogate_or_replace"),) raise GPGError( - 'Running {cmd} yielded return code {rc} with stdout: "{stdout}" and stderr: "{stderr}")'.format( - cmd=" ".join(command), - rc=p.returncode, - stdout=to_native(stdout, errors="surrogate_or_replace"), - stderr=to_native(stderr, errors="surrogate_or_replace"), - ) + f'Running {" ".join(command)} yielded return code {p.returncode} with stdout: "{stdout_n}" and stderr: "{stderr_n}")' ) return p.returncode, stdout, stderr diff --git a/tests/unit/plugins/module_utils/crypto/test_asn1.py b/tests/unit/plugins/module_utils/crypto/test_asn1.py index 0d1646f8..74e4fc04 100644 --- a/tests/unit/plugins/module_utils/crypto/test_asn1.py +++ b/tests/unit/plugins/module_utils/crypto/test_asn1.py @@ -78,7 +78,7 @@ TEST_CASES = [ @pytest.mark.parametrize("value, expected", TEST_CASES) def test_serialize_asn1_string_as_der(value, expected): actual = serialize_asn1_string_as_der(value) - print("%s | %s" % (value, base64.b16encode(actual).decode())) + print(f"{value} | {base64.b16encode(actual).decode()}") assert actual == expected @@ -121,10 +121,8 @@ def test_test_cases(value, expected, tmp_path): b_data = fd.read() hex_str = base64.b16encode(b_data).decode().lower() - print( - "%s | \\x%s" - % (value, "\\x".join([hex_str[i : i + 2] for i in range(0, len(hex_str), 2)])) - ) + value = "\\x".join([hex_str[i : i + 2] for i in range(0, len(hex_str), 2)]) + print(f"{value} | \\x{value}") # This is a know edge case where openssl asn1parse does not work properly. if value != "UTF8:café": diff --git a/tests/unit/plugins/module_utils/crypto/test_cryptography_support.py b/tests/unit/plugins/module_utils/crypto/test_cryptography_support.py index 2adf3f7b..6e31e0cc 100644 --- a/tests/unit/plugins/module_utils/crypto/test_cryptography_support.py +++ b/tests/unit/plugins/module_utils/crypto/test_cryptography_support.py @@ -201,7 +201,7 @@ if ( ], ) def test_parse_dn_component_failure(name, options, message): - with pytest.raises(OpenSSLObjectError, match="^%s$" % re.escape(message)): + with pytest.raises(OpenSSLObjectError, match=f"^{re.escape(message)}$"): _parse_dn_component(name, **options) @@ -245,5 +245,5 @@ def test_parse_dn(name, expected): ], ) def test_parse_dn_failure(name, message): - with pytest.raises(OpenSSLObjectError, match="^%s$" % re.escape(message)): + with pytest.raises(OpenSSLObjectError, match=f"^{re.escape(message)}$"): _parse_dn(name) diff --git a/tests/unit/plugins/module_utils/openssh/test_cryptography.py b/tests/unit/plugins/module_utils/openssh/test_cryptography.py index 4a281c90..ecf358ae 100644 --- a/tests/unit/plugins/module_utils/openssh/test_cryptography.py +++ b/tests/unit/plugins/module_utils/openssh/test_cryptography.py @@ -144,7 +144,7 @@ def test_default_key_params(keytype, size, passphrase, comment): "ed25519": 256, } - default_comment = "%s@%s" % (getuser(), gethostname()) + default_comment = f"{getuser()}@{gethostname()}" pair = OpensshKeypair.generate( keytype=keytype, size=size, passphrase=passphrase, comment=comment )