Improve error/warning messages w.r.t. YAML quoting (#1205)

* Remove superfluous conversions/assignments.

* Improve messages.
This commit is contained in:
Felix Fontein 2025-11-16 12:32:51 +01:00 committed by GitHub
parent e42423b949
commit c61c0e24b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 35 additions and 21 deletions

View File

@ -266,7 +266,9 @@ class Connection(ConnectionBase):
if not isinstance(val, str): if not isinstance(val, str):
raise AnsibleConnectionFailure( raise AnsibleConnectionFailure(
f"Non-string {what.lower()} found for extra_env option. Ambiguous env options must be " f"Non-string {what.lower()} found for extra_env option. Ambiguous env options must be "
f"wrapped in quotes to avoid them being interpreted. {what}: {val!r}" "wrapped in quotes to avoid them being interpreted when directly specified "
"in YAML, or explicitly converted to strings when the option is templated. "
f"{what}: {val!r}"
) )
local_cmd += [ local_cmd += [
b"-e", b"-e",

View File

@ -282,11 +282,11 @@ class Connection(ConnectionBase):
if not isinstance(val, str): if not isinstance(val, str):
raise AnsibleConnectionFailure( raise AnsibleConnectionFailure(
f"Non-string {what.lower()} found for extra_env option. Ambiguous env options must be " f"Non-string {what.lower()} found for extra_env option. Ambiguous env options must be "
f"wrapped in quotes to avoid them being interpreted. {what}: {val!r}" "wrapped in quotes to avoid them being interpreted when directly specified "
"in YAML, or explicitly converted to strings when the option is templated. "
f"{what}: {val!r}"
) )
kk = to_text(k, errors="surrogate_or_strict") data["Env"].append(f"{k}={v}")
vv = to_text(v, errors="surrogate_or_strict")
data["Env"].append(f"{kk}={vv}")
if self.get_option("working_dir") is not None: if self.get_option("working_dir") is not None:
data["WorkingDir"] = self.get_option("working_dir") data["WorkingDir"] = self.get_option("working_dir")

View File

@ -659,7 +659,9 @@ def _preprocess_env(
if not isinstance(value, str): if not isinstance(value, str):
module.fail_json( module.fail_json(
msg="Non-string value found for env option. Ambiguous env options must be " msg="Non-string value found for env option. Ambiguous env options must be "
f"wrapped in quotes to avoid them being interpreted. Key: {name}" "wrapped in quotes to avoid them being interpreted when directly specified "
"in YAML, or explicitly converted to strings when the option is templated. "
f"Key: {name}"
) )
final_env[name] = to_text(value, errors="surrogate_or_strict") final_env[name] = to_text(value, errors="surrogate_or_strict")
formatted_env = [] formatted_env = []
@ -947,7 +949,8 @@ def _preprocess_log(
value = to_text(v, errors="surrogate_or_strict") value = to_text(v, errors="surrogate_or_strict")
module.warn( module.warn(
f"Non-string value found for log_options option '{k}'. The value is automatically converted to {value!r}. " f"Non-string value found for log_options option '{k}'. The value is automatically converted to {value!r}. "
"If this is not correct, or you want to avoid such warnings, please quote the value." "If this is not correct, or you want to avoid such warnings, please quote the value,"
" or explicitly convert the values to strings when templating them."
) )
v = value v = value
options[k] = v options[k] = v

View File

@ -210,13 +210,14 @@ class ExecManager(BaseComposeManager):
self.stdin += "\n" self.stdin += "\n"
if self.env is not None: if self.env is not None:
for name, value in list(self.env.items()): for name, value in self.env.items():
if not isinstance(value, str): if not isinstance(value, str):
self.fail( self.fail(
"Non-string value found for env option. Ambiguous env options must be " "Non-string value found for env option. Ambiguous env options must be "
f"wrapped in quotes to avoid them being interpreted. Key: {name}" "wrapped in quotes to avoid them being interpreted when directly specified "
"in YAML, or explicitly converted to strings when the option is templated. "
f"Key: {name}"
) )
self.env[name] = to_text(value, errors="surrogate_or_strict")
def get_exec_cmd(self, dry_run: bool) -> list[str]: def get_exec_cmd(self, dry_run: bool) -> list[str]:
args = self.get_base_args(plain_progress=True) + ["exec"] args = self.get_base_args(plain_progress=True) + ["exec"]

View File

@ -296,13 +296,14 @@ class ExecManager(BaseComposeManager):
self.stdin += "\n" self.stdin += "\n"
if self.env is not None: if self.env is not None:
for name, value in list(self.env.items()): for name, value in self.env.items():
if not isinstance(value, str): if not isinstance(value, str):
self.fail( self.fail(
"Non-string value found for env option. Ambiguous env options must be " "Non-string value found for env option. Ambiguous env options must be "
f"wrapped in quotes to avoid them being interpreted. Key: {name}" "wrapped in quotes to avoid them being interpreted when directly specified "
"in YAML, or explicitly converted to strings when the option is templated. "
f"Key: {name}"
) )
self.env[name] = to_text(value, errors="surrogate_or_strict")
def get_run_cmd(self, dry_run: bool) -> list[str]: def get_run_cmd(self, dry_run: bool) -> list[str]:
args = self.get_base_args(plain_progress=True) + ["run"] args = self.get_base_args(plain_progress=True) + ["run"]

View File

@ -221,16 +221,17 @@ def main() -> None:
stdin: str | None = client.module.params["stdin"] stdin: str | None = client.module.params["stdin"]
strip_empty_ends: bool = client.module.params["strip_empty_ends"] strip_empty_ends: bool = client.module.params["strip_empty_ends"]
tty: bool = client.module.params["tty"] tty: bool = client.module.params["tty"]
env: dict[str, t.Any] = client.module.params["env"] env: dict[str, t.Any] | None = client.module.params["env"]
if env is not None: if env is not None:
for name, value in list(env.items()): for name, value in env.items():
if not isinstance(value, str): if not isinstance(value, str):
client.module.fail_json( client.module.fail_json(
msg="Non-string value found for env option. Ambiguous env options must be " msg="Non-string value found for env option. Ambiguous env options must be "
f"wrapped in quotes to avoid them being interpreted. Key: {name}" "wrapped in quotes to avoid them being interpreted when directly specified "
"in YAML, or explicitly converted to strings when the option is templated. "
f"Key: {name}"
) )
env[name] = to_text(value, errors="surrogate_or_strict")
if command is not None: if command is not None:
argv = shlex.split(command) argv = shlex.split(command)

View File

@ -914,8 +914,10 @@ def get_docker_environment(
for name, value in env.items(): for name, value in env.items():
if not isinstance(value, str): if not isinstance(value, str):
raise ValueError( raise ValueError(
"Non-string value found for env option. " "Non-string value found for env option. Ambiguous env options must be "
f"Ambiguous env options must be wrapped in quotes to avoid YAML parsing. Key: {name}" "wrapped in quotes to avoid them being interpreted when directly specified "
"in YAML, or explicitly converted to strings when the option is templated. "
f"Key: {name}"
) )
env_dict[name] = str(value) env_dict[name] = str(value)
elif env is not None and isinstance(env, list): elif env is not None and isinstance(env, list):

View File

@ -3077,10 +3077,14 @@
that: that:
- log_options_1 is changed - log_options_1 is changed
- log_options_2 is not changed - log_options_2 is not changed
- "'Non-string value found for log_options option \\'max-file\\'. The value is automatically converted to \\'5\\'. If this is not correct, or you want to - message in (log_options_2.warnings | default([]))
avoid such warnings, please quote the value.' in (log_options_2.warnings | default([]))"
- log_options_3 is not changed - log_options_3 is not changed
- log_options_4 is changed - log_options_4 is changed
vars:
message: >-
Non-string value found for log_options option 'max-file'. The value is automatically converted to '5'.
If this is not correct, or you want to avoid such warnings, please quote the value,
or explicitly convert the values to strings when templating them.
#################################################################### ####################################################################
## mac_address ##################################################### ## mac_address #####################################################