Skip to content

opentelemetry-configuration: substitute env vars after parsing (#5406)#5407

Open
ocelotl wants to merge 7 commits into
open-telemetry:mainfrom
ocelotl:issue_5406_env_substitution_in_comments
Open

opentelemetry-configuration: substitute env vars after parsing (#5406)#5407
ocelotl wants to merge 7 commits into
open-telemetry:mainfrom
ocelotl:issue_5406_env_substitution_in_comments

Conversation

@ocelotl

@ocelotl ocelotl commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Description

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 referenced only in a comment raised
EnvSubstitutionError and aborted loading, and self-documenting a config
file'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 embedded foo ${VAR} references resolve to
strings. JSON string values are substituted in place.

Fixes #5406

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • Added loader tests in opentelemetry-configuration/tests/file/test_loader.py:
    an undefined ${VAR} in a comment no longer crashes loading; unquoted
    standalone 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 value
    containing a newline cannot inject new mapping keys.
  • Updated test_env_substitution.py for the new post-parse, scalar-level
    behavior.
  • pytest opentelemetry-configuration/tests → 372 passed; pylint 10/10;
    ruff check/ruff format --check clean.

Does This PR Require a Contrib Repo Change?

  • No.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated


# Perform environment variable substitution
try:
content = substitute_env_vars(content)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@ocelotl
ocelotl marked this pull request as ready for review July 12, 2026 20:53
@ocelotl
ocelotl requested a review from a team as a code owner July 12, 2026 20:53
ocelotl added 6 commits July 15, 2026 18:12
…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.
@ocelotl
ocelotl force-pushed the issue_5406_env_substitution_in_comments branch from e079f84 to 8f8b4b2 Compare July 15, 2026 23:12
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.
@ocelotl
ocelotl requested a review from herin049 July 16, 2026 02:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Declarative configuration: environment variable substitution runs on raw file text before parsing, so YAML comments crash the configurator

2 participants