opentelemetry-configuration: substitute env vars after parsing (#5406)#5407
opentelemetry-configuration: substitute env vars after parsing (#5406)#5407ocelotl wants to merge 7 commits into
Conversation
|
|
||
| # Perform environment variable substitution | ||
| try: | ||
| content = substitute_env_vars(content) |
There was a problem hiding this comment.
This is where the bug (#5406) was. substitute_env_vars was applied to the entire raw file text at this point, before the file was parsed (yaml.safe_load / json.loads further down).
Because it operated on the unparsed text, ${VAR} references inside YAML comments — and inside mapping keys — were substituted exactly like real values. A comment such as # default is ${LEGACY_NAME} that referenced an undefined variable therefore raised EnvSubstitutionError and aborted loading, and any ${VAR} in a comment was silently rewritten.
This PR removes this pre-parse step and instead substitutes per configuration value after parsing (_parse_config_content → _substitute_env_in_yaml_node / _substitute_env_in_json_value), so comments and mapping keys are never substitution candidates, while node types are still resolved after substitution.
…telemetry#5406) Environment variable substitution ran on the raw configuration file text before parsing, so a ${VAR} reference inside a YAML comment was treated as a real substitution -- an undefined variable in a comment crashed loading, and documenting the substitution mechanism was impossible. Parse the file first, then substitute only within scalar values (never in comments or mapping keys), matching the configuration spec and the Java and Node.js implementations. For an unquoted standalone ${VAR} reference the YAML node's type tag is re-resolved from the substituted value so type coercion still applies (e.g. ${LIMIT} -> int); quoted or embedded references resolve to strings. JSON string values are substituted in place.
e079f84 to
8f8b4b2
Compare
substitute_env_vars is re-exported in opentelemetry.configuration.file.__all__, so renaming its parameter is a breaking public API change. Restore the parameter name to text to satisfy the public-symbols-check while keeping the docstring that explains the configuration-value semantics.
Description
Environment variable substitution ran on the raw configuration file text
before parsing, so a
${VAR}reference inside a YAML comment was treated asa real substitution. An undefined variable referenced only in a comment raised
EnvSubstitutionErrorand aborted loading, and self-documenting a configfile's use of the substitution mechanism was impossible.
This changes the loader to parse the file first and then substitute
environment variables only within scalar values (never in comments or mapping
keys), matching the configuration spec
and the Java/Node.js implementations. Substitution is applied at the YAML node
level so node types are still interpreted after substitution: an unquoted
standalone
${VAR}takes the resolved value's YAML type (e.g.${LIMIT}→int), while quoted
"${VAR}"and embeddedfoo ${VAR}references resolve tostrings. JSON string values are substituted in place.
Fixes #5406
Type of change
How Has This Been Tested?
opentelemetry-configuration/tests/file/test_loader.py:an undefined
${VAR}in a comment no longer crashes loading; unquotedstandalone references are type-coerced (and pass JSON-schema validation for
integer fields); quoted references stay strings; embedded references resolve
to strings; mapping keys and
$$escapes are left untouched; and a valuecontaining a newline cannot inject new mapping keys.
test_env_substitution.pyfor the new post-parse, scalar-levelbehavior.
pytest opentelemetry-configuration/tests→ 372 passed;pylint10/10;ruff check/ruff format --checkclean.Does This PR Require a Contrib Repo Change?
Checklist: