Skip to content

Move RabbitMQ env-var credential override into a dedicated RabbitMQConfig class - #65

Open
bladeroot wants to merge 5 commits into
hiqdev:masterfrom
bladeroot:rabbitmq-env-override-separate-class
Open

Move RabbitMQ env-var credential override into a dedicated RabbitMQConfig class#65
bladeroot wants to merge 5 commits into
hiqdev:masterfrom
bladeroot:rabbitmq-env-override-separate-class

Conversation

@bladeroot

@bladeroot bladeroot commented Aug 21, 2026

Copy link
Copy Markdown
Member

Summary

Follow-up to #64 (HQD-355). connection_parameters() in RabbitMQ.py isn't the right place to decide whether credentials come from an env var or the config file — it's a config-dict → pika.ConnectionParameters builder, not a config-resolution layer. It's also called from two independent entry points (Daemon.consume() for heppyd, bin/heppyc directly) that were each separately assembling the RabbitMQ sub-config already, so the override logic had no single natural owner.

Test plan

  • python3 -m unittest discover -s tests — 137 passed (moved/extended the env-var tests from test_RabbitMQ.py into a new test_RabbitMQConfig.py, added a test for the empty-env-var case)

Summary by CodeRabbit

  • New Features

    • Added centralized RabbitMQ configuration handling.
    • Automatically assigns a default queue name when none is provided.
    • Supports environment-based credential overrides, including empty values.
  • Bug Fixes

    • Ensured RabbitMQ connections consistently use the resolved configuration.
  • Tests

    • Added coverage for default and custom queues, credential fallbacks, and environment overrides.

…nfig class

connection_parameters() in RabbitMQ.py isn't the right place to decide
whether credentials come from an env var or the config file - it's a
config-dict -> pika.ConnectionParameters builder, not a config-resolution
layer. It's also invoked from two different entry points (Daemon.consume()
for heppyd, bin/heppyc directly) that were each separately assembling the
RabbitMQ sub-config already (config.get('RabbitMQ', {}) + queue default),
so the override logic had no single natural owner.

RabbitMQConfig now owns resolving the final RabbitMQ.* dict: config file
values, the default 'heppy-<name>' queue name, and RABBITMQ_USERNAME/
RABBITMQ_PASSWORD env-var overrides - used identically by Daemon.py and
bin/heppyc. RabbitMQ.py's connection_parameters() goes back to a plain
config-dict reader, same as before the env-var override existed.

Also fixes a correctness bug from that override: it used `or`, so a
present-but-empty env var (e.g. a secretKeyRef resolving to "") silently
fell back to the config file's value instead of overriding - reintroducing
the exact kind of drift the override was meant to prevent. RabbitMQConfig
checks presence (`in os.environ`) instead.
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@bladeroot, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 674449c7-499e-4bb1-861e-030cf716d94d

📥 Commits

Reviewing files that changed from the base of the PR and between 0e9a1f7 and 1dd4be5.

📒 Files selected for processing (5)
  • bin/heppyd
  • bin/reppyd
  • heppy/Daemon.py
  • heppy/RabbitMQConfig.py
  • tests/test_RabbitMQConfig.py

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c24061a-33e7-45fe-b86f-4184fded4bff

📥 Commits

Reviewing files that changed from the base of the PR and between 2e1f55d and 0e9a1f7.

📒 Files selected for processing (6)
  • bin/heppyc
  • heppy/Daemon.py
  • heppy/RabbitMQ.py
  • heppy/RabbitMQConfig.py
  • tests/test_RabbitMQ.py
  • tests/test_RabbitMQConfig.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

RabbitMQ configuration resolution now uses RabbitMQConfig. The resolver applies queue defaults and environment credential overrides. RabbitMQ setup paths use the resolved configuration, and connection credential handling no longer reads environment variables directly.

Changes

RabbitMQ configuration

Layer / File(s) Summary
Configuration resolution and validation
heppy/RabbitMQConfig.py, tests/test_RabbitMQConfig.py
Adds RabbitMQConfig.resolve() with queue defaults, environment overrides, and tests for credential precedence.
RabbitMQ setup integration
bin/heppyc, heppy/Daemon.py
Routes RabbitMQ setup through RabbitMQConfig(config).resolve().
Connection credential handling
heppy/RabbitMQ.py, tests/test_RabbitMQ.py
Uses configured credentials in connection_parameters and removes obsolete direct environment-selection tests.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 0e9a1

The PR centralizes RabbitMQ credential and queue configuration resolution while preserving the connection-parameter builder behavior; no actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 5 files. (1 skipped: 1 unsupported.) Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes moving RabbitMQ environment-variable credential overrides into the new RabbitMQConfig class.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Daemon.consume() shouldn't decide when/how to resolve its own transport
config either - same reasoning as RabbitMQ.py earlier in this branch.
bin/heppyd and bin/reppyd both construct Daemon and already assemble
Config there; they now resolve RabbitMQConfig too and hand Daemon the
finished dict via a required constructor argument, matching how
bin/heppyc already hands RPCClient an already-resolved rabbit_config.
Daemon no longer imports RabbitMQConfig or touches os.environ, even
indirectly.

reppyd resolves it too, even though its SocketServer path never uses it
today - consume()'s branch is decided by config content, not by which
bin/ script launched it, so both entrypoints need to hand Daemon a real
rabbit_config rather than relying on a silent None default.
Same _FILE convention the official rabbitmq Docker image already uses for
RABBITMQ_DEFAULT_PASS_FILE, so a deployment can point both the broker and
every worker at the same mounted secret file instead of (or in addition
to) plain env vars, without inventing a new convention.

Setting both a var and its _FILE counterpart for the same key raises
rather than silently picking one - consistent with the "presence, not
truthiness" rule already applied to the plain env vars.
…TIALS_FILE

The previous _FILE-per-key design was justified as "the same convention
the official rabbitmq Docker image uses" - that's factually wrong. The
official image's docker-entrypoint.sh actively rejects
RABBITMQ_DEFAULT_USER_FILE/RABBITMQ_DEFAULT_PASS_FILE with a hard error
("set but deprecated") since 3.9, pointing users at a real config file
instead - it doesn't support that pattern, this version included.

Replaced with a single RABBITMQ_CREDENTIALS_FILE pointing at one JSON file
shaped {"username": ..., "password": ...} - matching how the credential
pair is already kept together as one Kubernetes Secret
(ahnames-epp-rabbitmq) rather than two, so that Secret can be mounted and
read as one unit. Setting it together with either plain env var is still
rejected outright, same "presence, not truthiness" and "no silent
precedence" rules as before.
dict(self.config.get('RabbitMQ', {})) leaned on .get()'s default
parameter to express "this section or an empty dict" - correct, but the
branch was implicit. _config_section() spells out the same two outcomes
as an explicit if/return instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant