Skip to content

Configure backbeat from the environment, without rewriting the config file - #2809

Open
francoisferrand wants to merge 7 commits into
development/9.6from
improvement/BB-808
Open

Configure backbeat from the environment, without rewriting the config file#2809
francoisferrand wants to merge 7 commits into
development/9.6from
improvement/BB-808

Conversation

@francoisferrand

@francoisferrand francoisferrand commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

The docker entrypoint applied env-var configuration by rewriting conf/config.json in place with jq. That breaks when the config is mounted read-only, which is what zenko-operator does: setting any mapped variable made the container exit at startup. The mapping was also a hand-maintained shell table duplicated from the joi schema, and had drifted from it — LOG_LEVEL rejected the warn and error levels the schema accepts, and a few variables whose config section had since been removed were written back in, so setting one stopped the process from starting.

Overrides are now applied in memory before validation, with their names derived from the schemas themselves: a new configuration field is settable from the environment as soon as it is declared. Names that don't follow from the config path are annotated next to the field they name, which is how the historic ones keep working, and the handful of variables setting several fields at once stay in an explicit table. Values go through the schema like any other configuration, so an invalid one fails the startup instead of being silently ignored. docs/configuration.md documents the whole thing.

Every variable the entrypoint applied is pinned by a test, since zenko-operator and Federation set them and Federation forwards arbitrary ones from the field. Two deliberate exceptions, both already dead: MONGODB_HOSTS no longer selects the mongo log source dropped in BB-836, and the lifecycle rules and local cache variables are ignored rather than fatal.

Removed variables

The following variables are not supported anymore, and will now be ignored. They used to be worse than useless: the entrypoint wrote them into configuration sections the schema no longer knows, and validation then rejected the whole file, so setting one of them stopped the process from starting.

  • EXTENSIONS_LIFECYCLE_RULES_EXPIRATION_ENABLED,
    EXTENSIONS_LIFECYCLE_RULES_NC_VERSION_EXPIRATION_ENABLED,
    EXTENSIONS_LIFECYCLE_RULES_TRANSITIONS_ENABLED,
    EXTENSIONS_LIFECYCLE_RULES_ABORT_INCOMPLETE_MPU_ENABLED: the rules supported by the lifecycle extension are configured with EXTENSIONS_LIFECYCLE_SUPPORTED_LIFECYCLE_RULES.
  • REDIS_LOCALCACHE_HOST, REDIS_LOCALCACHE_PORT: the local cache is not part of the configuration.

MONGODB_HOSTS keeps setting queuePopulator.mongo.replicaSetHosts, but no longer selects the mongo log source, which the queue populator dropped: a deployment relying on it has to set queuePopulator.logSource itself.

Issue: BB-808

@bert-e

bert-e commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Hello francoisferrand,

My role is to assist you with the merge of this
pull request. Please type @bert-e help to get information
on this process, or consult the user documentation.

Available options
name description privileged authored
/after_pull_request Wait for the given pull request id to be merged before continuing with the current one.
/bypass_author_approval Bypass the pull request author's approval
/bypass_build_status Bypass the build and test status
/bypass_commit_size Bypass the check on the size of the changeset TBA
/bypass_incompatible_branch Bypass the check on the source branch prefix
/bypass_jira_check Bypass the Jira issue check
/bypass_peer_approval Bypass the pull request peers' approval
/bypass_leader_approval Bypass the pull request leaders' approval
/approve Instruct Bert-E that the author has approved the pull request. ✍️
/create_pull_requests Allow the creation of integration pull requests.
/create_integration_branches Allow the creation of integration branches.
/no_octopus Prevent Wall-E from doing any octopus merge and use multiple consecutive merge instead
/unanimity Change review acceptance criteria from one reviewer at least to all reviewers
/wait Instruct Bert-E not to run until further notice.
Available commands
name description privileged
/help Print Bert-E's manual in the pull request.
/status Print Bert-E's current status in the pull request.
/clear Remove all comments from Bert-E from the history TBA
/retry Re-start a fresh build TBA
/build Re-start a fresh build TBA
/force_reset Delete integration branches & pull requests, and restart merge process from the beginning.
/reset Try to remove integration branches unless there are commits on them which do not appear on the source branch.

Status report is not available.

@bert-e

bert-e commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Incorrect fix version

The Fix Version/s in issue BB-808 contains:

  • 9.6.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.0.31

  • 9.1.13

  • 9.2.8

  • 9.3.8

  • 9.4.4

  • 9.5.0

Please check the Fix Version/s of BB-808, or the target
branch of this pull request.

Comment thread lib/BackbeatMetadataProxy.js
@francoisferrand
francoisferrand changed the base branch from development/9.0 to development/9.5 August 18, 2026 16:24
@bert-e

bert-e commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Incorrect fix version

The Fix Version/s in issue BB-808 contains:

  • 9.6.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.5.0

Please check the Fix Version/s of BB-808, or the target
branch of this pull request.

@francoisferrand
francoisferrand requested review from a team, DarkIsDude and delthas August 18, 2026 16:48

@DarkIsDude DarkIsDude left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry for the review. I thought it'll be a fast one but finally not really.

With what we have, if we have for example SERVER_PORT as an env var and a extension.Replication.Server.Port, the env var can have an impact. Those very short env var name and generic, can be very dangerous. Setting a short env var car have a wide impact ? What do you think ? Maybe I'm not very clear, let me know by slack if it's the case.

Comment thread Dockerfile
Comment thread extensions/replication/ReplicationConfigValidator.js
Comment thread lib/config/configItems.joi.js
Comment thread lib/config/envOverrides.js Outdated
Comment thread docs/configuration.md Outdated
Comment thread extensions/gc/GarbageCollectorConfigValidator.js
Comment thread lib/config/extensionConfigValidator.js
Comment thread tests/unit/lib/config/envOverrides.spec.js Outdated
Comment thread lib/config/envOverrides.js
Comment thread lib/config/envOverrides.js
@DarkIsDude

Copy link
Copy Markdown

Should land to the next release ?

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.19355% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 75.95%. Comparing base (929145d) to head (e5ae10f).

Files with missing lines Patch % Lines
lib/config/envOverrides.js 98.68% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

Files with missing lines Coverage Δ
extensions/gc/GarbageCollectorConfigValidator.js 100.00% <100.00%> (ø)
extensions/ingestion/IngestionConfigValidator.js 100.00% <100.00%> (ø)
extensions/lifecycle/LifecycleConfigValidator.js 100.00% <100.00%> (ø)
...ns/mongoProcessor/MongoProcessorConfigValidator.js 100.00% <100.00%> (ø)
...nsions/notification/NotificationConfigValidator.js 100.00% <100.00%> (ø)
...ns/oplogPopulator/OplogPopulatorConfigValidator.js 100.00% <100.00%> (ø)
...tensions/replication/ReplicationConfigValidator.js 100.00% <100.00%> (ø)
lib/Config.js 81.14% <100.00%> (+5.02%) ⬆️
lib/config.joi.js 100.00% <100.00%> (ø)
lib/config/configItems.joi.js 96.42% <100.00%> (ø)
... and 3 more

... and 2 files with indirect coverage changes

Components Coverage Δ
Bucket Notification 80.25% <100.00%> (-0.03%) ⬇️
Core Library 82.30% <99.03%> (+0.34%) ⬆️
Ingestion 70.04% <100.00%> (-0.06%) ⬇️
Lifecycle 80.45% <100.00%> (-0.01%) ⬇️
Oplog Populator 85.80% <100.00%> (-0.03%) ⬇️
Replication 62.13% <100.00%> (+0.12%) ⬆️
Bucket Scanner 85.76% <ø> (ø)
@@                 Coverage Diff                 @@
##           development/9.6    #2809      +/-   ##
===================================================
+ Coverage            75.77%   75.95%   +0.18%     
===================================================
  Files                  200      203       +3     
  Lines                13922    14007      +85     
===================================================
+ Hits                 10549    10639      +90     
+ Misses                3363     3358       -5     
  Partials                10       10              
Flag Coverage Δ
api:retry 9.44% <64.51%> (+0.33%) ⬆️
api:routes 9.21% <64.51%> (+0.33%) ⬆️
bucket-scanner 85.76% <ø> (ø)
ft_test:queuepopulator 11.33% <64.51%> (+0.30%) ⬆️
ingestion 12.58% <64.51%> (+0.31%) ⬆️
lifecycle 19.59% <64.51%> (+0.27%) ⬆️
notification 1.01% <0.00%> (-0.01%) ⬇️
oplogPopulator 0.13% <0.00%> (-0.01%) ⬇️
replication 19.12% <64.51%> (+0.26%) ⬆️
unit 55.22% <99.19%> (+0.33%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bert-e

bert-e commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Incorrect fix version

The Fix Version/s in issue BB-808 contains:

  • 9.6.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.5.1

  • 9.6.0

Please check the Fix Version/s of BB-808, or the target
branch of this pull request.

@francoisferrand
francoisferrand changed the base branch from development/9.5 to development/9.6 August 20, 2026 17:39
@bert-e

bert-e commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Waiting for approval

The following approvals are needed before I can proceed with the merge:

  • the author

  • 2 peers

The following reviewers are expecting changes from the author, or must review again:

The log configuration only defaulted as a whole object: a section
setting just one level left the other undefined, and werelogs was then
configured with an undefined dump level. The per-extension log section
turned that gap into a hard failure by requiring both levels, which
leaves no way to set only one — and an override from the environment
always produces such a partial section, since a variable names a single
field.

Each level now carries its own default, shared by the global and the
per-extension schemas, so setting one leaves the other at its default
instead of unset or rejected.

Issue: BB-808
docker-entrypoint.sh applied every environment variable by rewriting
conf/config.json in place with jq. That fails outright when the file is
mounted read-only, as zenko does: setting any mapped variable crashed
the container at startup. The mapping was also a hand-maintained shell
table duplicated from the joi schema, and drifting from it.

Overrides are now applied in memory before validation, and their names
are derived from the schema itself, so a new configuration field becomes
settable from the environment as soon as it is declared. The names that
do not follow from the config path are annotated next to the field they
name, and the few variables setting several fields at once are kept in
an explicit table. Values go through the schema like any other
configuration: an invalid one fails the startup instead of being
silently ignored.

Every variable the entrypoint used to apply keeps working, pinned by a
test: Zenko and Federation set them, and Federation forwards arbitrary
ones from the field. Two exceptions, both already already broken:
* the `EXTENSIONS_LIFECYCLE_RULES_*` and `REDIS_LOCALCACHE_*`
  variables wrote config sections the schema no longer knows, so setting
  one made validation reject the whole file and the process fail to
  start - they are now simply ignored;
* `MONGODB_HOSTS` no longer selects the "mongo" log source -not
  supported anymore- and only sets the replica set hosts of the shared
  MongoDB connection.

Issue: BB-808
Setting a per-extension log level silently reset the dump level to a
constant, dropping whatever a deployment had configured globally. An
extension now inherits the levels it does not configure from the global
log config, so it overrides only what it names — which is also what an
override from the environment produces, since a variable names a single
field.

Extension schemas reach the global configuration through the validation
context. The extension validators were already given it, but as the
configuration object still being built, so nothing could be read from
it. The extension configurations are kept out of it: they are validated
one after the other, so referencing one would resolve differently
depending on the order of the configuration file, and an extension must
not depend on another one.

Issue: BB-808
extension validators re-derive the envVarMapping it on every call,
memoizing to avoid the redundant cost (~30ms each time).

Not critical since it happens only once on startup, but adds up in
tests.

Issue: BB-808
The complexity was artificial, change mapping to simplify.

Issue: BB-808
Move tests of each source file into its own spec, and ensure each module
is tested at its own level.

Issue: BB-808

@DarkIsDude DarkIsDude left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Check also the CI even if I guess it's related to flakyness

Comment thread docs/configuration.md
Comment thread docs/configuration.md

- `TIME_PROGRESSION_FACTOR`: decreases the weight of a day, to expedite the
lifecycle of objects.
- `EXPIRE_ONE_DAY_EARLIER`, `TRANSITION_ONE_DAY_EARLIER`: deprecated in favor of

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@francoisferrand do we have a follow-up for that ?

Comment thread lib/config.joi.js
Comment on lines +91 to +92
// redis is reached either through its sentinels or directly: the two modes
// are exclusive, and each has the settings of its own

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
// redis is reached either through its sentinels or directly: the two modes
// are exclusive, and each has the settings of its own

It's just what happens one line after 🙏

Comment thread lib/config.joi.js
port: joi.number().required(),
})),
]).required(),
// group name of the master the sentinels watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
// group name of the master the sentinels watch

Comment on lines +46 to +47
// the levels default individually, so that setting one of them, from the
// configuration or from the environment, leaves the other one alone

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
// the levels default individually, so that setting one of them, from the
// configuration or from the environment, leaves the other one alone

const BOOTSTRAPLIST_MORE = 'EXTENSIONS_REPLICATION_DEST_BOOTSTRAPLIST_MORE';

/**
* Under its historic name, the bootstrap list holds the servers of the single

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Even if I get the point, I have the feeling that this comment is a more a context that you want to output from your brain than a real useful comment. The comment don't describe what happens for the value provided ?

Comment thread docs/configuration.md Outdated

const { getField, setField } = require('./fields');

// A container exposes a single probe endpoint, shared by all the probe servers

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

*/
function applyEnvOverrides(config, schema, prefix = [], env = process.env) {
if (config === null || typeof config !== 'object') {
// leave the invalid configuration for joi to report

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If you really wants to keep it, move it under the function description then or the return value ?

Comment thread lib/config/envOverrides.js Outdated
zookeeperPath: joi.string().required(),
bucketTasksTopic: joi.string().required(),
objectTasksTopic: joi.string().required(),
bucketTasksTopic: joi.string().required().meta({ env: 'BUCKET_TASK_TOPIC' }),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

One last thing that came out the review. Should we add tests for that ? I'm mitigated as this is pure config joi but if not caught can be a pain (not sure we have tests for all them in Zenko...).

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.

by "this" do you mean the meta/env annotation? in that case, we actually have tests: these variables are the "legacy" variables, and there are test validating that they indeed are still working as expected.

@francoisferrand

Copy link
Copy Markdown
Contributor Author

Check also the CI even if I guess it's related to flakyness

this is the (known) issue about librdkafka revert breaking the newest tests, shall be fixed by rebasing on the fix once merged, just waiting confirmation for which way to go.

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.

3 participants