Skip to content

Perform semantic blueprint diffs via daft#7466

Merged
andrewjstone merged 7 commits intomainfrom
daft
Feb 5, 2025
Merged

Perform semantic blueprint diffs via daft#7466
andrewjstone merged 7 commits intomainfrom
daft

Conversation

@andrewjstone
Copy link
Contributor

This PR introduces the generation of automated blueprint diffs via daft.

It is still necessary to massage the automated diff output into existing types so that we can present them graphically. This is performed via a wrapper, BlueprintDiffSummary, which is also used in tests.

This change is 100% backwards compatible and generates identical diff output to the hand rolled diffs. Functionality was recently added to daft to allow lazy diffing, via stopping recursion and returning a Leaf even if a field of a struct is itself a diffable struct. Doing this allows us to not recures into smaller structures like ZpoolName that we want to treat opaquely, and also allows us to maintain some handwritten diffs for output that is not changing any time soon, such as BlueprintMetadata and ClickhouseClusterConfig.

This PR supercedes #7402 and removes all previously merged diffus related visitors. It also removes some left over types dealing with diffing collections and blueprints which is not currently supported.

Follow up PRs will expand our diff output using the new functionality to add things like dataset disposition, etc...

This PR introduces the generation of automated blueprint diffs via
[daft](https://github.com/oxidecomputer/daft).

It is still necessary to massage the automated diff output into existing
types so that we can present them graphically. This is performed via
a wrapper, `BlueprintDiffSummary`, which is also used in tests.

This change is 100% backwards compatible and generates identical diff
output to the hand rolled diffs. Functionality was recently added to
`daft` to [allow lazy diffing](oxidecomputer/daft#16),
via stopping recursion and returning a `Leaf` even if a field
of a struct is itself a diffable struct. Doing this allows us to not
recures into smaller structures like `ZpoolName` that we want to treat
opaquely, and also allows us to maintain some handwritten diffs for
output that is not changing any time soon, such as `BlueprintMetadata`
and `ClickhouseClusterConfig`.

This PR supercedes #7402
and removes all previously merged diffus related visitors. It also
removes some left over types dealing with diffing collections and
blueprints which is not currently supported.

Follow up PRs will expand our diff output using the new functionality
to add things like dataset disposition, etc...
Copy link
Contributor

@jgallagher jgallagher left a comment

Choose a reason for hiding this comment

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

Nice - daft is very slick!


// We can't do the same for removals unfortunately. We prematurely
// prune decommissioned sleds, but there may still be zones, disks,
// or datasets that have not yet been removed. We must check for this.
Copy link
Contributor

Choose a reason for hiding this comment

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

I was going to ask if we could switch this to just looking at sled_state once #7470 lands, but I guess that would break diffs for blueprints involving decommissioned sleds made before that change landed. Maybe once we start pruning old blueprints, then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, all things that break diffs should come in follow ups.

}

self.diff.clickhouse_cluster_config.before
!= self.diff.clickhouse_cluster_config.after
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we also need to check the cockroach stuff (fingerprint, preserve_downgrade)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe? I was just keeping this compatible with what was already here, but I will add that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now I'm wondering if we also want to consider internal_dns_version and external_dns_version as well ?

@davepacheco any thoughts here?

// Do we have any errors? If so, create a "reason" string.
let mut reason = String::new();
// These first two checks are only for backwards compatibility. They are
// all included in the zone_type comparison below.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we drop these two since they're covered by the later zone_type check? If that changes the diffs from tests, maybe do that as a small followup PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I anticipate a few cleanup tasks in a follow up that break backwards compatibility. I'll add this one.

generation_before: Generation,
generation_after: Generation,
zone_diffs: impl Iterator<Item = &'a BlueprintZoneConfigDiff<'a>>,
) -> (BpDiffZonesModified, BpDiffZoneErrors) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't love this interface, but I'm not sure what to suggest instead. Do you think an enum with 3 cases might be clearer? Something like

enum BpDiffZonesResult {
    Ok(BpDiffZonesModified), // all comparisons are fine
    Err(BpDiffZoneErrors), // all comparisons failed
    Mixed(BpDiffZonesModified, BpDiffZoneErrors), // some of each
}

since we expect to basically always be in the Ok(_) case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eh, matching that in callers seems worse.

@andrewjstone andrewjstone merged commit ae63a61 into main Feb 5, 2025
18 checks passed
@andrewjstone andrewjstone deleted the daft branch February 5, 2025 21:40
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.

2 participants