Support multiple environment variable placeholders in config values#2070
Support multiple environment variable placeholders in config values#2070aantn wants to merge 2 commits into
Conversation
…and Holmes add-on env vars
- Warn that {{ env.X }} replaces the entire field value (no prefix/suffix concatenation)
- Document runner.additional_env_froms for bulk-injecting Secret/ConfigMap keys
- Clarify that runner and HolmesGPT pods do not share environment variables, so secrets used by both must be declared in both additional_env_vars blocks
- Mention holmes.operator.additionalEnvVars and holmes.mcpAddons.{aws,azure}.additionalEnvVars for users running those add-ons
…ering the whole value
Previously, get_env_replacement returned the env var's value as the new field
value, so `"Bearer {{ env.TOKEN }}"` was silently replaced with just the token
and any prefix/suffix was dropped. Switch to re.sub so only the placeholder is
substituted, leaving the rest of the string intact. Multiple placeholders in
the same field are also now supported (e.g. `"{{ env.USER }}:{{ env.PASSWORD }}"`).
The "return None when there is no placeholder" contract is preserved so
existing callers in runner_config.py and replace_env_vars_values keep working.
Also updates the docs to advertise the supported concatenation/multi-placeholder
patterns.
WalkthroughThis PR enhances environment variable placeholder substitution in Robusta configuration by introducing a new regex-based mechanism that replaces multiple ChangesEnvironment Variable Placeholder Substitution
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
✅ Docker image ready for
Use this tag to pull the image for testing. 📋 Copy commandsgcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:554009b
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:554009b me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:554009b
docker push me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:554009bPatch Helm values in one line: helm upgrade --install robusta robusta/robusta \
--reuse-values \
--set runner.image=me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:554009b |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/robusta/core/playbooks/playbook_utils.py`:
- Around line 19-24: The code currently treats empty environment variables as
missing by checking falsiness in the env lookup; update the existence checks to
use None semantics so empty strings are allowed: in the function that reads
env_var_value (the block using os.environ.get(name, None) and the subsequent if
not env_var_value check), change the condition to check "is None" before
logging/raising; likewise update the truthy checks in replace_env_vars_values
(the checks at the locations referenced in the comment) to use "is not None" so
that empty-string substitutions are preserved rather than treated as absent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e365fa0a-b831-48ab-8769-013525033bae
📒 Files selected for processing (2)
docs/setup-robusta/configuration-secrets.rstsrc/robusta/core/playbooks/playbook_utils.py
| env_var_value = os.environ.get(name, None) | ||
| if not env_var_value: | ||
| msg = f"ENV var replacement {env_values[0]} does not exist for param: {value}" | ||
| msg = f"ENV var replacement {name} does not exist for param: {value}" | ||
| logging.error(msg) | ||
| raise Exception(msg) | ||
| return env_var_value |
There was a problem hiding this comment.
Allow empty env vars; only fail when the variable is truly missing.
At Line 20, if not env_var_value treats VAR="" as nonexistent and raises, which blocks valid empty-value substitutions. Use is None for existence checks. Also switch truthy checks in replace_env_vars_values (Lines 33/37/41) to is not None so empty replacements are preserved.
Suggested patch
def get_env_replacement(value: str) -> Optional[str]:
if not _ENV_PLACEHOLDER_RE.search(value):
return None
def _sub(match: "re.Match[str]") -> str:
name = match.group(1).strip()
- env_var_value = os.environ.get(name, None)
- if not env_var_value:
+ env_var_value = os.environ.get(name)
+ if env_var_value is None:
msg = f"ENV var replacement {name} does not exist for param: {value}"
logging.error(msg)
raise Exception(msg)
return env_var_value
return _ENV_PLACEHOLDER_RE.sub(_sub, value)
def replace_env_vars_values(values: Dict) -> Dict:
for key, value in values.items():
if isinstance(value, str):
env_var_value = get_env_replacement(value)
- if env_var_value:
+ if env_var_value is not None:
values[key] = env_var_value
elif isinstance(value, SecretStr):
env_var_value = get_env_replacement(value.get_secret_value())
- if env_var_value:
+ if env_var_value is not None:
values[key] = SecretStr(env_var_value)
elif isinstance(value, dict):
env_var_value = replace_env_vars_values(value)
- if env_var_value:
+ if env_var_value is not None:
values[key] = env_var_value🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/robusta/core/playbooks/playbook_utils.py` around lines 19 - 24, The code
currently treats empty environment variables as missing by checking falsiness in
the env lookup; update the existence checks to use None semantics so empty
strings are allowed: in the function that reads env_var_value (the block using
os.environ.get(name, None) and the subsequent if not env_var_value check),
change the condition to check "is None" before logging/raising; likewise update
the truthy checks in replace_env_vars_values (the checks at the locations
referenced in the comment) to use "is not None" so that empty-string
substitutions are preserved rather than treated as absent.
Summary
Enhanced environment variable substitution in Robusta configuration to support multiple placeholders in a single field and improved the regex pattern for more robust matching.
Key Changes
{{ env.VAR }}placeholders (e.g.,"{{ env.USER }}:{{ env.PASSWORD }}") instead of just one"Bearer {{ env.TOKEN }}")_ENV_PLACEHOLDER_REthat properly handles whitespace and prevents over-matchingre.sub()with a callback function for proper multi-placeholder replacementImplementation Details
r"{{\s*env\.([^}\s]+)\s*}}"is more precise:env.}or whitespace to avoid capturing extra characters_sub()that processes each match independently, enabling proper handling of multiple placeholders in one valueDocumentation
Added comprehensive documentation covering:
runner.additional_env_fromsfeature for bulk secret injectionhttps://claude.ai/code/session_013EFjPwGU1FDY6fs6rcELac