Skip to content

storewolf: preserve parent settings when applying defaults - #1073

Closed
xiaotianlyu wants to merge 1 commit into
bottlerocket-os:developfrom
xiaotianlyu:fix/storewolf-preserve-legacy-ntp
Closed

xiaotianlyu wants to merge 1 commit into
bottlerocket-os:developfrom
xiaotianlyu:fix/storewolf-preserve-legacy-ntp

Conversation

@xiaotianlyu

@xiaotianlyu xiaotianlyu commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Description of changes:

Storewolf currently skips a default only when the exact datastore key already exists. During an upgrade, an existing setting may use a parent key while the new defaults use named child keys.

For example, bottlerocket-os/bottlerocket#4923 migrates the legacy settings.ntp.time-servers list to named settings under settings.ntp.time-servers.<name>.*. Storewolf would otherwise add the new default servers when the legacy parent key already exists. This can cause custom NTP configurations or an empty server list to receive
default servers during an upgrade.

Update Storewolf to skip child defaults when an ancestor key already exists. Unrelated defaults continue to be populated normally.

Testing done:

  • cargo test -p storewolf skips_descendants_of_existing_setting
  • cargo clippy -p storewolf --all-targets -- -D warnings
  • cargo fmt --manifest-path sources/Cargo.toml --all -- --check
  • git diff --check

Terms of contribution:

By submitting this pull request, I agree that this contribution is
dual-licensed under the terms of both the Apache License, version 2.0,
and the MIT license.

Skip child defaults when the datastore already contains their parent
setting. This preserves legacy aggregate values during migration.

Signed-off-by: Melody Lyu <tianlyu@amazon.com>
@xiaotianlyu
xiaotianlyu force-pushed the fix/storewolf-preserve-legacy-ntp branch from 5f53328 to 1bf2baf Compare October 1, 2026 21:19
@xiaotianlyu xiaotianlyu changed the title storewolf: preserve existing parent settings storewolf: preserve parent settings when applying defaults Oct 1, 2026
Ok(())
}

fn key_or_ancestor_populated(key: &Key, existing_data: &HashSet<Key>) -> bool {

@vyaghras vyaghras Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So if we have a.b in datastore, will it skip adding a.b.c in the datastore? Skipping all descendants when an ancestor exists will silently drop defaults for genuinely-new child settings (e.g. a future host-containers.control.user-data).

Ok(())
}

fn key_or_ancestor_populated(key: &Key, existing_data: &HashSet<Key>) -> bool {

@vyaghras vyaghras Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use the existing Key::starts_with_segments instead of raw-string prefix matching — it's correct by structure, not by string coincidence, and avoids a second divergent prefix mechanism.

}

fn key_or_ancestor_populated(key: &Key, existing_data: &HashSet<Key>) -> bool {
existing_data.iter().any(|existing_key| {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This compares each default key against every existing key on every boot, so the cost is existing keys x default keys. Could we walk the default key's ancestors and look each one up in the HashSet instead?

@xiaotianlyu

Copy link
Copy Markdown
Contributor Author

Closing this PR because we agreed to retain the legacy NTP defaults and make the forward migration a no-op. With that approach, this Storewolf change is no longer needed.

@xiaotianlyu xiaotianlyu closed this Oct 2, 2026
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