Skip to content

Conversation

@jgallagher
Copy link
Contributor

Sorry for the size of this PR. Most of the bulk of the diff is made up of mechanical changes to tests; I don't think there's a way to split this up any smaller. If you ignore whitespace that will trim a few hundred lines off the diff.

This PR should make zero behavioral changes. The main thrust of the PR is to replace the four maps in Blueprint (sled_state, blueprint_zones, blueprint_disks, blueprint_datasets) with a single map containing the config for each sled (sleds: BTreeMap<SledUuid, BlueprintSledConfig>). Only one expectorate file changed (and that's because I changed the test; it was previously doing a thing we can't do anymore with the combined maps).

Nontrivial fallout from this change:

  • BlueprintBuilder no longer has to do work to ingest a parent blueprint where sleds present in blueprint_zones were missing in one or more of the other three maps.
  • ... but nexus-db-model has to do that work now instead, to allow us to continue to load old blueprints from the db that didn't require all four maps to have consistent keys. We should be able to drop this and instead bail! after R14, since upgrading to that release will involve creating a blueprint that uses this combined map (and thus guarantees the blueprint in the db has entries for all its fields).
  • blippy got to delete several checks that are now statically impossible.
  • The blueprint diff implementation similarly got to delete a bunch of summary fields that were complicated to construct; the daft output from the sleds map is now directly usable in place of all those summary fields.

I think this is pretty clearly a win, but there are a couple places where users of blueprints or diffs are a little uglier IMO:

  • Tests that were constructing a blueprint that only cared about one of the four maps now have to fill in the full sleds map. This is straightforward and mechanical, but is a little noisy.
  • The executor library had substeps that took the individual maps as arguments. Those maps no longer exist, so I changed them to take iterators instead. This was also straightforward and mechanical, but even more noisy.
  • Using the blueprint summary.diff.sleds directly in tests instead of the old summary sets is more verbose. (Personally I prefer this change, despite the verbosity, because I found it easier to look at daft's docs then remember what all the helper methods in the diff summary did. But I could see others feeling differently.)

Fixes #7078. After this change, it'll be possible to start work on #7309 (merging the disks/datasets/zone sled-agent endpoints into one), since this restructuring will allow us to tag the combined config with a single generation.

Copy link
Contributor

@andrewjstone andrewjstone left a comment

Choose a reason for hiding this comment

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

This is so great.

/// Iterate over the ids of all sleds in the blueprint
pub fn sleds(&self) -> impl Iterator<Item = SledUuid> + '_ {
self.blueprint_zones.keys().copied()
self.sleds.keys().copied()
Copy link
Contributor

Choose a reason for hiding this comment

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

This is so much more logical now!

);

// Look up the sled state
let sled_state = sled_state
Copy link
Contributor

Choose a reason for hiding this comment

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

🥳

seen_sleds.insert(sled_id);
}

// Now create and display a table of zones/datasets on sleds that don't
Copy link
Contributor

Choose a reason for hiding this comment

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

Garbage be gone!

pub fn new(before: &'a Blueprint, after: &'a Blueprint) -> Self {
let diff = before.diff(after);

let modified_zones_diff = diff
Copy link
Contributor

Choose a reason for hiding this comment

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

Truly a dream come true.

}
};

// Combine the four separately-stored maps into the one blueprint map.
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good, and makes sense.

};
}
}
blueprint1.blueprint_datasets.remove(&decommision_sled_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like it was wrong before. Maybe I missed the disks one at least.


let zones_added =
&summary.zones_on_modified_sled(&sled_id).unwrap().zones.added;
let zones_added = &summary
Copy link
Contributor

Choose a reason for hiding this comment

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

Possibly the only drawback I see in this PR. However, I also prefer it as all this code is macro generated rather than the handrolled monstrosity that existed before.

@jgallagher jgallagher merged commit e9302b7 into main Feb 28, 2025
17 checks passed
@jgallagher jgallagher deleted the john/blueprint-merge-maps branch February 28, 2025 20:28
jgallagher added a commit that referenced this pull request Mar 4, 2025
Builds on #7713, and is followup from
#7713 (comment).
In #7652 I changed all the executor substeps to take iterators instead
of `&BTreeMap` references that no longer existed, but that introduced a
weird split where the top-level caller had to filter the blueprint down
to just the items that the inner functions expected. @smklein pointed
out one place where the inner code was being extra defensive, which was
just more confusing than anything.

This PR removes that split: the top-level executor now always passes a
full `&Blueprint` down, and the inner modules are responsible for doing
their own filtering as appropriate. To easy testing, I kept the versions
that take an iterator of already-filtered items as private `*_impl`
functions that the new functions-that-take-a-full-`Blueprint` themselves
call too.
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.

Blueprint structure allows a variety of "illegal" combinations

3 participants