Conversation
03bf716 to
e6a722e
Compare
e6a722e to
9d27ff4
Compare
nexus/db-model/src/deployment.rs
Outdated
|
|
||
| #[derive(Queryable, Clone, Debug, Selectable, Insertable)] | ||
| #[diesel(table_name = bp_single_measurements)] | ||
| //#[diesel(check_for_backend(diesel::pg::Pg))] |
nexus/db-model/src/deployment.rs
Outdated
| }, | ||
| hash: *self | ||
| .image_artifact_sha256 | ||
| .expect("this should always be set"), |
There was a problem hiding this comment.
Can the field be non-optional (and the corresponding db row have a NOT NULL constraint)?
nexus/db-model/src/deployment.rs
Outdated
| pub id: DbTypedUuid<MeasurementKind>, | ||
|
|
||
| pub image_artifact_sha256: Option<ArtifactHash>, | ||
| pub prune: bool, |
There was a problem hiding this comment.
Discussed in chat but noting for completeness - I think we can drop the prune field since the planner has access to both the current and previous TUF repo.
nexus/types/src/deployment.rs
Outdated
| } | ||
| } | ||
|
|
||
| impl From<BTreeSet<BlueprintSingleMeasurement>> for BlueprintMeasurements { |
There was a problem hiding this comment.
These Froms seem fine-ish but surprising - could wherever we're currently using BTreeSet<BlueprintSingleMeasurement> use BlueprintMeasurements instead?
nexus/types/src/deployment.rs
Outdated
| self.measurements.insert(single); | ||
| } | ||
|
|
||
| // An empty measurement set here corresponds to the install dataset |
There was a problem hiding this comment.
Is this property guaranteed? Wondering if there are edge cases where we could have an empty set of measurements but that didn't imply "use the install dataset" - maybe dev/test systems? Or if this is a surprising security-related property in the future sometime if someone assumes "empty set" means "won't be able to talk" but it actually means "falls back to whatever was most recently written to the install dataset (possibly months/years ago)".
There was a problem hiding this comment.
Yeah this is a bit of a strange edge case. I did a first pass with this being an enum like BlueprintZoneImageSource but I'm trying to remember why doing that here was ugly. It's possible I went a layer too far in getting rid of indirection. I'll play around with this more.
That said, there eventually should be no case in the future when this is empty past the initial install. As we get further along and more confident I expect we'll want to make that a stronger assertion.
There was a problem hiding this comment.
This turned out to be more doable than I remembered, perhaps now that things are matured
ae2e508 to
bc950ef
Compare
| match measurement { | ||
| BlueprintMeasurements::Artifacts { artifacts } => artifacts | ||
| .iter() | ||
| .map(move |d| { | ||
| BpTableRow::from_strings( | ||
| state, | ||
| vec![d.hash.to_string(), d.version.to_string()], | ||
| ) | ||
| }) | ||
| .collect::<Vec<BpTableRow>>() | ||
| .into_iter(), | ||
| BlueprintMeasurements::InstallDataset => { | ||
| vec![BpTableRow::from_strings( | ||
| state, | ||
| vec![ | ||
| "install dataset".to_string(), | ||
| "(no version)".to_string(), | ||
| ], | ||
| )] | ||
| .into_iter() | ||
| .collect::<Vec<BpTableRow>>() | ||
| .into_iter() |
There was a problem hiding this comment.
I need to fix this up to use Either
| match self { | ||
| BlueprintMeasurements::InstallDataset => { | ||
| std::iter::empty::<&BlueprintSingleMeasurement>() | ||
| .collect::<Vec<&BlueprintSingleMeasurement>>() | ||
| .into_iter() | ||
| } | ||
| BlueprintMeasurements::Artifacts { artifacts } => artifacts | ||
| .iter() | ||
| .collect::<Vec<&BlueprintSingleMeasurement>>() | ||
| .into_iter(), | ||
| } |
There was a problem hiding this comment.
Fix this to use Either
We don't actually update the measuremenst right now, that will come in follow on work.
| ); | ||
| } | ||
|
|
||
| let raw_measurements: Vec<(BpSingleMeasurement, Option<TufArtifact>)> = { |
There was a problem hiding this comment.
I think this is in the wrong place within this function, after the changes @smklein made to ensure we don't read partially-deleted blueprints (#9703). About 50 lines above this is:
// ================================================================
// STAGE 3: Parse and validate all loaded data
//
// At this point, we know the blueprint exists (wasn't deleted).
// Any validation errors from here indicate real database
// corruption, not a torn read from concurrent deletion.
// ================================================================
and we're not expected to do any more reads from the DB in this stage, so I think this needs to go above into "STAGE 1". (Maybe we should break the stages up into three methods to make this mistake more difficult? But that probably has its own annoyances.)
I think this may also mean we don't need the
// We start with measurements from the install dataset, if
// there's anything in the database this will get overwritten
comment above - if we've already read raw_measurements before we get to that point, hopefully we can fill in the correct value immediately?
There was a problem hiding this comment.
Good catch. I'll see about making this change and mayyybe see about refactoring but I'm not great with diesel. Maybe I should just file a bug instead?
| pub zones: IdOrdMap<BlueprintZoneConfig>, | ||
| pub remove_mupdate_override: Option<MupdateOverrideUuid>, | ||
| pub host_phase_2: BlueprintHostPhase2DesiredSlots, | ||
| #[serde(default = "BlueprintMeasurements::default")] |
There was a problem hiding this comment.
Do we need a #[serde(default)] here? I don't think we need to parse old BlueprintSledConfigs.
There was a problem hiding this comment.
This was something I added when I thought I had a different problem. I can remove it.
| } | ||
| } | ||
|
|
||
| /// The [`BpTable`] schema for desired host phase 2 contents |
| id UUID NOT NULL, | ||
|
|
||
| image_artifact_sha256 STRING(64) NOT NULL, | ||
| PRIMARY KEY (blueprint_id, id) |
There was a problem hiding this comment.
Turbo-nit - these two lines are indented differently from the columns above
No description provided.