Skip to content

Commit

Permalink
Support diffing blueprints via Diffus
Browse files Browse the repository at this point in the history
This is the second step in #7240. The next steps will use this support
to replace our handrolled code for generating diffs and generate output
from the diffus based diffs.
  • Loading branch information
andrewjstone committed Dec 18, 2024
1 parent e27e4f3 commit be228e8
Show file tree
Hide file tree
Showing 22 changed files with 205 additions and 36 deletions.
34 changes: 31 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ derive-where = "1.2.7"
# Having the i-implement-... feature here makes diesel go away from the workspace-hack
diesel = { version = "2.2.4", features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes", "postgres", "r2d2", "chrono", "serde_json", "network-address", "uuid"] }
diesel-dtrace = "0.4.2"
#diffus = { version = "0.10.0", features = ["uuid-impl", "derive"] }
diffus = { git = "https://github.com/oxidecomputer/diffus", branch = "oxide/main", features = ["uuid-impl", "derive", "newtype-uuid-impl", "oxnet-impl"] }
dns-server = { path = "dns-server" }
dns-server-api = { path = "dns-server-api" }
dns-service-client = { path = "clients/dns-service-client" }
Expand Down Expand Up @@ -576,7 +578,7 @@ secrecy = "0.8.0"
semver = { version = "1.0.23", features = ["std", "serde"] }
serde = { version = "1.0", default-features = false, features = [ "derive", "rc" ] }
serde_human_bytes = { git = "https://github.com/oxidecomputer/serde_human_bytes", branch = "main" }
serde_json = "1.0.132"
serde_json = "1.0.133"
serde_path_to_error = "0.1.16"
serde_tokenstream = "0.2"
serde_urlencoded = "0.7.1"
Expand Down
3 changes: 2 additions & 1 deletion clickhouse-admin/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ camino.workspace = true
camino-tempfile.workspace = true
chrono.workspace = true
derive_more.workspace = true
diffus.workspace = true
itertools.workspace = true
omicron-common.workspace = true
omicron-workspace-hack.workspace = true
Expand All @@ -25,4 +26,4 @@ expectorate.workspace = true

[dev-dependencies]
slog-async.workspace = true
slog-term.workspace = true
slog-term.workspace = true
3 changes: 3 additions & 0 deletions clickhouse-admin/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use atomicwrites::AtomicFile;
use camino::Utf8PathBuf;
use chrono::{DateTime, Utc};
use derive_more::{Add, AddAssign, Display, From};
use diffus::Diffus;
use itertools::Itertools;
use omicron_common::api::external::Generation;
use schemars::{
Expand Down Expand Up @@ -56,6 +57,7 @@ pub const OXIMETER_CLUSTER: &str = "oximeter_cluster";
JsonSchema,
Serialize,
Deserialize,
Diffus,
)]
pub struct KeeperId(pub u64);

Expand All @@ -75,6 +77,7 @@ pub struct KeeperId(pub u64);
JsonSchema,
Serialize,
Deserialize,
Diffus,
)]
pub struct ServerId(pub u64);

Expand Down
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ async-trait.workspace = true
backoff.workspace = true
camino.workspace = true
chrono.workspace = true
diffus.workspace = true
dropshot.workspace = true
futures.workspace = true
hex.workspace = true
Expand Down
16 changes: 16 additions & 0 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use anyhow::Context;
use api_identity::ObjectIdentity;
use chrono::DateTime;
use chrono::Utc;
use diffus::{edit, Diffable, Diffus};
use dropshot::HttpError;
pub use dropshot::PaginationOrder;
pub use error::*;
Expand Down Expand Up @@ -211,6 +212,7 @@ impl<'a> TryFrom<&DataPageParams<'a, NameOrId>> for DataPageParams<'a, Uuid> {
)]
#[display("{0}")]
#[serde(try_from = "String")]
#[derive(Diffus)]
pub struct Name(String);

/// `Name::try_from(String)` is the primary method for constructing an Name
Expand Down Expand Up @@ -614,6 +616,7 @@ impl JsonSchema for RoleName {
Eq,
PartialOrd,
Ord,
Diffus,
)]
pub struct ByteCount(u64);

Expand Down Expand Up @@ -748,6 +751,7 @@ impl From<ByteCount> for i64 {
PartialEq,
PartialOrd,
Serialize,
Diffus,
)]
pub struct Generation(u64);

Expand Down Expand Up @@ -1935,6 +1939,17 @@ impl JsonSchema for L4PortRange {
)]
pub struct MacAddr(pub macaddr::MacAddr6);

impl<'a> Diffable<'a> for MacAddr {
type Diff = (&'a Self, &'a Self);
fn diff(&'a self, other: &'a Self) -> edit::Edit<'a, Self> {
if self == other {
edit::Edit::Copy(self)
} else {
edit::Edit::Change((self, other))
}
}
}

impl MacAddr {
// Guest MAC addresses begin with the Oxide OUI A8:40:25. Further, guest
// address are constrained to be in the virtual address range
Expand Down Expand Up @@ -2098,6 +2113,7 @@ impl JsonSchema for MacAddr {
Deserialize,
Serialize,
JsonSchema,
Diffus,
)]
pub struct Vni(u32);

Expand Down
20 changes: 17 additions & 3 deletions common/src/api/internal/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
address::NUM_SOURCE_NAT_PORTS,
api::external::{self, BfdMode, ImportExportPolicy, Name, Vni},
};
use diffus::Diffus;
use oxnet::{IpNet, Ipv4Net, Ipv6Net};
use schemars::JsonSchema;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
Expand Down Expand Up @@ -35,6 +36,7 @@ use super::nexus::HostIdentifier;
Serialize,
JsonSchema,
Hash,
Diffus,
)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum NetworkInterfaceKind {
Expand All @@ -48,7 +50,15 @@ pub enum NetworkInterfaceKind {

/// Information required to construct a virtual network interface
#[derive(
Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Hash,
Clone,
Debug,
Deserialize,
Serialize,
JsonSchema,
PartialEq,
Eq,
Hash,
Diffus,
)]
pub struct NetworkInterface {
pub id: Uuid,
Expand All @@ -68,7 +78,9 @@ pub struct NetworkInterface {
/// outbound network connections from guests or services.
// Note that `Deserialize` is manually implemented; if you make any changes to
// the fields of this structure, you must make them to that implementation too.
#[derive(Debug, Clone, Copy, Serialize, JsonSchema, PartialEq, Eq, Hash)]
#[derive(
Debug, Clone, Copy, Serialize, JsonSchema, PartialEq, Eq, Hash, Diffus,
)]
pub struct SourceNatConfig {
/// The external address provided to the instance or service.
pub ip: IpAddr,
Expand Down Expand Up @@ -871,7 +883,9 @@ pub struct ExternalIpGatewayMap {
}

/// Describes the purpose of the dataset.
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, EnumCount)]
#[derive(
Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, EnumCount, Diffus,
)]
#[cfg_attr(feature = "testing", derive(test_strategy::Arbitrary))]
pub enum DatasetKind {
// Durable datasets for zones
Expand Down
4 changes: 4 additions & 0 deletions common/src/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use anyhow::bail;
use camino::{Utf8Path, Utf8PathBuf};
use diffus::Diffus;
use omicron_uuid_kinds::DatasetUuid;
use omicron_uuid_kinds::PhysicalDiskUuid;
use omicron_uuid_kinds::ZpoolUuid;
Expand Down Expand Up @@ -176,6 +177,7 @@ impl DatasetName {
Hash,
PartialOrd,
Ord,
Diffus,
)]
pub struct GzipLevel(u8);

Expand Down Expand Up @@ -218,6 +220,7 @@ impl FromStr for GzipLevel {
Hash,
PartialOrd,
Ord,
Diffus,
)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CompressionAlgorithm {
Expand Down Expand Up @@ -412,6 +415,7 @@ impl DatasetsManagementResult {
Serialize,
Deserialize,
JsonSchema,
Diffus,
)]
pub struct DiskIdentity {
pub vendor: String,
Expand Down
5 changes: 3 additions & 2 deletions common/src/zpool_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! Zpool labels and kinds shared between Nexus and Sled Agents
use camino::{Utf8Path, Utf8PathBuf};
use diffus::Diffus;
use omicron_uuid_kinds::ZpoolUuid;
use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
Expand All @@ -15,7 +16,7 @@ pub const ZPOOL_INTERNAL_PREFIX: &str = "oxi_";

/// Describes the different classes of Zpools.
#[derive(
Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema,
Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema, Diffus,
)]
#[serde(rename_all = "snake_case")]
pub enum ZpoolKind {
Expand All @@ -29,7 +30,7 @@ pub enum ZpoolKind {
///
/// This expects that the format will be: `ox{i,p}_<UUID>` - we parse the prefix
/// when reading the structure, and validate that the UUID can be utilized.
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Diffus)]
pub struct ZpoolName {
id: ZpoolUuid,
kind: ZpoolKind,
Expand Down
1 change: 1 addition & 0 deletions nexus-sled-agent-shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
workspace = true

[dependencies]
diffus.workspace = true
illumos-utils.workspace = true
omicron-common.workspace = true
omicron-passwords.workspace = true
Expand Down
11 changes: 10 additions & 1 deletion nexus-sled-agent-shared/src/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use std::net::{IpAddr, Ipv6Addr, SocketAddr, SocketAddrV6};

use diffus::Diffus;
use omicron_common::{
api::{
external::{ByteCount, Generation},
Expand Down Expand Up @@ -173,7 +174,15 @@ impl OmicronZoneConfig {

/// Describes a persistent ZFS dataset associated with an Omicron zone
#[derive(
Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Hash,
Clone,
Debug,
Deserialize,
Serialize,
JsonSchema,
PartialEq,
Eq,
Hash,
Diffus,
)]
pub struct OmicronZoneDataset {
pub pool_name: ZpoolName,
Expand Down
1 change: 1 addition & 0 deletions nexus/reconfigurator/planning/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ anyhow.workspace = true
clickhouse-admin-types.workspace = true
chrono.workspace = true
debug-ignore.workspace = true
diffus.workspace = true
gateway-client.workspace = true
illumos-utils.workspace = true
indexmap.workspace = true
Expand Down
7 changes: 7 additions & 0 deletions nexus/reconfigurator/planning/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ mod test {
use chrono::Utc;
use clickhouse_admin_types::ClickhouseKeeperClusterMembership;
use clickhouse_admin_types::KeeperId;
use diffus::Diffable;
use expectorate::assert_contents;
use nexus_sled_agent_shared::inventory::ZoneKind;
use nexus_types::deployment::blueprint_zone_type;
Expand Down Expand Up @@ -909,6 +910,12 @@ mod test {
"2 -> 3 (expect new NTP zone on new sled):\n{}",
diff.display()
);
let diffus_diff = blueprint3.diff(&blueprint2);
println!("_______DIFFUS __________\n");
let change = diffus_diff.change();
println!("{:#?}", diffus_diff);
println!("{:#?}", change);
println!("________DIFFUS __________\n");
assert_contents(
"tests/output/planner_basic_add_sled_2_3.txt",
&diff.display().to_string(),
Expand Down
Loading

0 comments on commit be228e8

Please sign in to comment.