Skip to content

A hand-edited or interrupted settings-file migration heals on stores that expose the managed PostgreSQL on the network - #4465

Merged
erikdarlingdata merged 2 commits into
devfrom
fix/managed-conf-unstamped-command-line-keys
Sep 27, 2026
Merged

erikdarlingdata merged 2 commits into
devfrom
fix/managed-conf-unstamped-command-line-keys

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Why

A store that exposes its managed PostgreSQL on the network always starts it with listen_addresses and port forced onto the pg_ctl -o command line, which outranks the settings file unconditionally. The rendered darling-managed.conf line for listen_addresses always stays loopback-only, so pg_file_settings reports that file row with error = "setting could not be applied" — not merely applied = false — because its value differs from what's actually in force.

A prior fix taught ManagedConfMigrationRunner.VerifyStepB to skip these command-line-owned keys. The same trap existed in the MigratedUnstamped re-verification path: it treats ANY error row whose source file is darling-managed.conf as a failure, with no such skip. A store in that state (reached by a hand edit of the file, or a crash inside Step B) reported Failed on every start, and its verified stamp never healed, on any store with a configured network endpoint.

The sweep

Path Affected Why
MigratedUnstamped re-verification Yes — fixed Scanned every darling-managed.conf error row with no key skip; listen_addresses's command-line-override error row always failed it on an exposed store.
Step A ResumePending / CompareAndFinish / ManagedConfFileSettings.Compare No Compare only flags a NEW error row relative to the BEFORE snapshot taken from the same live server; the command-line override is already in force both before and after Step A runs (it doesn't change across the migration), so the same error row appears on both sides and is never "new."
Step B VerifyStepB Already fixed (prior PR) Already skips DarlingStoreHostProfile.CommandLineOnlyKeys.
ComputeAndStoreManagedConfVerdictsAsync (verdicts) No, already correct Already gives CommandLineOnlyKeys a fixed HostSettingVerdict.CommandLine row before any classification runs, and only scans pg_file_settings errors for the eight sizing keys — listen_addresses/port are never in that error scan at all.
Startup heal (HealLegacyMaintenanceWorkMem, MigrateManagedConfAsync's other branches) No Only touches maintenance_work_mem/legacy conf structure; never reads a pg_file_settings error row for listen_addresses or port.
--check-settings (GatherSettingProfilesAsync) No Only classifies the eight sizing keys via AttributeManagedSetting/ClassifyVerdict; never queries pg_file_settings error rows, and never touches CommandLineOnlyKeys at all.
ManagedConfFile.RenderBody N/A (pinned, not fixed) Not a verification path — the source of the always-loopback line every path above depends on. Pinned directly (see below) since every other pin's assumption rests on it.

What changes

  • ManagedConfMigrationRunner.FindUnstampedManagedFileErrors: extracts the MigratedUnstamped scan into a small, unit-testable static helper, reusing DarlingStoreHostProfile.CommandLineOnlyKeys (never copying the list) to skip port/listen_addresses error rows, exactly as VerifyStepB already does.
  • DarlingManagedPostgres.cs's MigratedUnstamped case now calls that helper instead of inlining the scan.
  • No other verification surface changed; the sweep table above explains why each was already correct.

Pins

All in Darling.Tests (unit, no live database):

  • FindUnstampedManagedFileErrors_ListenAddressesOverriddenByCommandLine_IsNotAnError — the command-line listen_addresses error row alone reports HasError = false.
  • FindUnstampedManagedFileErrors_PortOverriddenByCommandLine_IsNotAnError — same for port.
  • FindUnstampedManagedFileErrors_RealErrorOnOtherKey_StillReportsError — a real error row on another key (e.g. work_mem) still reports HasError = true with that key named, alongside a skipped listen_addresses row that does not appear in the mismatched keys.
  • RenderBody_ListenAddresses_IsAlwaysLoopbackOnly — a fast pin that ManagedConfFile.RenderBody always renders listen_addresses = '127.0.0.1', the fact every path above depends on.

Row shapes reuse the address 192.0.2.10 (RFC 5737 documentation range) where an address stand-in is needed; no real IP appears.

RED (runtime, on origin/dev): ManagedConfMigrationRunner.FindUnstampedManagedFileErrors does not exist on dev — a compile-only RED for the new pins (the method itself is the extraction). DarlingManagedPostgres.cs's MigratedUnstamped case is a private branch of a private async method (MigrateManagedConfAsync), reachable only from EnsureRunningAsync's own switch on the migration state — there is no public seam that reaches it without a real Windows PostgreSQL start, and the extraction is behavior-preserving (the helper's loop is the exact inline loop that used to sit in that case, plus the skip), so no new runtime-reachable seam is introduced or needed. The mutations below prove the fix and the render assumption it depends on, at runtime, against the code as actually committed:

Mutation A — the skip itself: deleted the CommandLineOnlyKeys skip block from FindUnstampedManagedFileErrors (all of it, not just the listen_addresses branch) and rebuilt. All three FindUnstampedManagedFileErrors_* facts went RED, nothing else:

Darling.Tests.ManagedConfMigrationRunnerTests.FindUnstampedManagedFileErrors_ListenAddressesOverriddenByCommandLine_IsNotAnError [FAIL]
Darling.Tests.ManagedConfMigrationRunnerTests.FindUnstampedManagedFileErrors_PortOverriddenByCommandLine_IsNotAnError [FAIL]
Darling.Tests.ManagedConfMigrationRunnerTests.FindUnstampedManagedFileErrors_RealErrorOnOtherKey_StillReportsError [FAIL]
Darling.Tests  Total: 21, Errors: 0, Failed: 3, Skipped: 0, Not Run: 0, Time: 0.319s

(The third fact fails too: with the skip gone, hasError still comes out true there, but mismatchedKeys now also carries the listen_addresses row the fact asserts is absent.) Reverted (git checkout -- the one file); git diff --stat empty; rebuilt clean.

Mutation B — the render assumption every path above depends on: changed DarlingManagedPostgres.BuildConfAppend's rendered listen_addresses = '127.0.0.1' literal to '0.0.0.0' and rebuilt. RenderBody_ListenAddresses_IsAlwaysLoopbackOnly went RED, nothing else:

Darling.Tests.ManagedConfFileTests.RenderBody_ListenAddresses_IsAlwaysLoopbackOnly [FAIL]
Darling.Tests  Total: 34, Errors: 0, Failed: 1, Skipped: 0, Not Run: 0, Time: 0.330s

Reverted; git diff --stat empty; rebuilt clean. Both mutations went RED exactly as expected, so no test-only fix was needed.

After both reverts and the merge with dev's own VerifyStepB command-line skip (landed separately on dev in the meantime, keeping both fixes and both test sets side by side), the green totals: ManagedConfMigrationRunnerTests 24/24, ManagedConfFileTests 34/34, ManagedConfMigrationTests 43/43, DocCommentHygieneTests 77/77.

Build: dotnet build Darling/Darling.Tests/Darling.Tests.csproj -c Release -p:EnableWindowsTargeting=true — 0 warnings, 0 errors.

Gated tests

Not run here, because they need Windows and the PostgreSQL runtime packages. These are the tests the test-only run must show passing:

  • ManagedConfUpgradePathTests.*_Gated
  • UpgradeInPlace_*
  • RuntimeAdvance_*
  • Postgres17Store_*

CHANGELOG entry

SECTION: Fixed
ENTRY:

…eys too

pg_file_settings reports an error row for listen_addresses on an exposed
store: the command line always outranks the rendered darling-managed.conf
line (which stays loopback-only), so PostgreSQL reports that mismatch as
an error, not merely applied=false. The MigratedUnstamped path (a hand
edit of darling-managed.conf, or a crash inside Step B) treated ANY error
row from that file as a failure, so an exposed store in that state
reported Failed on every start and its stamp never healed.

Extracts the scan into FindUnstampedManagedFileErrors and reuses
DarlingStoreHostProfile.CommandLineOnlyKeys, the same skip
ManagedConfMigrationRunner.VerifyStepB already applies for the sibling
case.
…mped-command-line-keys

# Conflicts:
#	Darling/Darling.Tests/ManagedConfMigrationRunnerTests.cs
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 27, 2026 13:35
@erikdarlingdata
erikdarlingdata merged commit 6c3b026 into dev Sep 27, 2026
24 of 26 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/managed-conf-unstamped-command-line-keys branch September 27, 2026 13:35
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