Skip to content

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

Open
francoisferrand wants to merge 3 commits into
development/9.5from
improvement/BB-808
Open

Configure backbeat from the environment, without rewriting the config file#2809
francoisferrand wants to merge 3 commits into
development/9.5from
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.

Issue: BB-808

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
@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
ENV AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE=1

ENTRYPOINT ["tini", "-g", "--", "/usr/src/app/docker-entrypoint.sh"]
ENTRYPOINT ["tini", "-g", "--"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

tini is still useful ?


const { MAX_QUEUED_DEFAULT } = require('../../lib/constants').backbeatConsumer;

// the historic env var names put the backend before `RETRY`, e.g.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What the goal of the comment ?

const logLevelJoi = joi.alternatives()
.try('error', 'warn', 'info', 'debug', 'trace');

// the levels default individually, so that setting one of them, from the

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It was a decision made by Sylvain to required both or none. Why did you change that ?

@@ -0,0 +1,368 @@
'use strict';

/* eslint-disable no-param-reassign */

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

That's a bit aggresive ? Why do you want to disable it globally ?

Comment thread docs/configuration.md
The fields of an object with unconstrained keys, such as `kafka.producerParams`,
have no derived name, and neither have the fields the schema forbids.

## Values

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm not sure we need that, it's pretty standard ?

}

module.exports = configValidator;
module.exports = extensionConfigValidator('gc', joiSchema);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is never tested and can be a huge source of regression (same for other extentions)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No test at all ?

});

it('should not derive a name for the params BackbeatProducer sets itself', () => {
const names = [...envVarMappings(backbeatConfigJoi).keys()];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not really easy to read this test. Better to use your own config and don't reuse production one

try {
return JSON.parse(value);
} catch (err) {
throw new Error(`invalid JSON value for ${name}: ${err.message}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this is never tested ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'll let you decide but, ready the test file, we could split this one with:

  • One for generic function (getPath, setPath, ...)
  • One for managing composite env var
  • One for managing replacement
  • One for the extention logic
  • Of course an index to expose what is needed to validation

I'm not sure it's useful, so I'll let you decide

@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.24242% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 75.73%. Comparing base (52b9510) to head (06dcc11).

Files with missing lines Patch % Lines
lib/config/envOverrides.js 99.01% 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 82.44% <100.00%> (+6.32%) ⬆️
lib/config.joi.js 100.00% <ø> (ø)
lib/config/configItems.joi.js 96.42% <100.00%> (ø)
... and 2 more

... and 3 files with indirect coverage changes

Components Coverage Δ
Bucket Notification 80.25% <100.00%> (-0.03%) ⬇️
Core Library 81.78% <99.15%> (-0.16%) ⬇️
Ingestion 70.04% <100.00%> (-0.06%) ⬇️
Lifecycle 80.45% <100.00%> (-0.01%) ⬇️
Oplog Populator 85.80% <100.00%> (-0.03%) ⬇️
Replication 62.04% <100.00%> (+0.02%) ⬆️
Bucket Scanner 85.76% <ø> (ø)
@@                 Coverage Diff                 @@
##           development/9.5    #2809      +/-   ##
===================================================
- Coverage            75.76%   75.73%   -0.03%     
===================================================
  Files                  200      202       +2     
  Lines                13922    14023     +101     
===================================================
+ Hits                 10548    10621      +73     
- Misses                3364     3392      +28     
  Partials                10       10              
Flag Coverage Δ
api:retry 9.42% <57.57%> (+0.31%) ⬆️
api:routes 9.19% <57.57%> (+0.32%) ⬆️
bucket-scanner 85.76% <ø> (ø)
ft_test:queuepopulator 9.56% <57.57%> (-1.43%) ⬇️
ingestion 12.56% <57.57%> (+0.29%) ⬆️
lib 9.14% <57.57%> (+0.31%) ⬆️
lifecycle 19.55% <57.57%> (+0.25%) ⬆️
notification 1.01% <0.00%> (-0.01%) ⬇️
oplogPopulator 0.13% <0.00%> (-0.01%) ⬇️
replication 19.09% <57.57%> (+0.24%) ⬆️
unit 55.27% <99.24%> (+0.39%) ⬆️

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.

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