Skip to content

Commit

Permalink
Merge branch 'main' into john/planner-zones-ready-for-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jgallagher committed Feb 24, 2025
2 parents e59a39d + 06c17ba commit cfb06bc
Show file tree
Hide file tree
Showing 155 changed files with 10,033 additions and 4,150 deletions.
568 changes: 377 additions & 191 deletions Cargo.lock

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ gateway-test-utils = { path = "gateway-test-utils" }
gateway-types = { path = "gateway-types" }
gethostname = "0.5.0"
glob = "0.3.2"
guppy = "0.17.16"
guppy = "0.17.17"
headers = "0.4.0"
heck = "0.5"
hex = "0.4.3"
Expand Down Expand Up @@ -455,7 +455,7 @@ ipnetwork = { version = "0.21", features = ["schemars", "serde"] }
ispf = { git = "https://github.com/oxidecomputer/ispf" }
key-manager = { path = "key-manager" }
kstat-rs = "0.2.4"
libc = "0.2.169"
libc = "0.2.170"
libipcc = { git = "https://github.com/oxidecomputer/libipcc", rev = "fdffa212373a8f92473ea5f411088912bf458d5f" }
libfalcon = { git = "https://github.com/oxidecomputer/falcon", branch = "main" }
libnvme = { git = "https://github.com/oxidecomputer/libnvme", rev = "dd5bb221d327a1bc9287961718c3c10d6bd37da0" }
Expand Down Expand Up @@ -555,7 +555,7 @@ pem = "3.0"
# false: petname = { workspace = true, default-features = false }.
petname = { version = "2.0.2", default-features = false, features = ["default-rng", "default-words"] }
petgraph = "0.6.5"
postgres-protocol = "0.6.7"
postgres-protocol = "0.6.8"
predicates = "3.1.3"
pretty_assertions = "1.4.1"
pretty-hex = "0.4.1"
Expand Down Expand Up @@ -589,20 +589,20 @@ regress = "0.9.1"
repo-depot-api = { path = "sled-agent/repo-depot-api" }
repo-depot-client = { path = "clients/repo-depot-client" }
reqwest = { version = "0.12", default-features = false }
ring = "0.17.8"
ring = "0.17.11"
rpassword = "7.3.1"
rstest = "0.23.0"
rustfmt-wrapper = "0.2"
rustls = "0.22.2"
rustls-pemfile = "2.2.0"
rustyline = "14.0.0"
samael = { version = "0.0.17", features = ["xmlsec"] }
samael = { version = "0.0.18", features = ["xmlsec"] }
schemars = "0.8.21"
secrecy = "0.8.0"
semver = { version = "1.0.23", features = ["std", "serde"] }
semver = { version = "1.0.25", 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.133"
serde_json = "1.0.139"
serde_path_to_error = "0.1.16"
serde_tokenstream = "0.2"
serde_urlencoded = "0.7.1"
Expand All @@ -614,7 +614,7 @@ signal-hook = "0.3"
signal-hook-tokio = { version = "0.3", features = [ "futures-v0_3" ] }
sigpipe = "0.1.3"
similar = { version = "2.6.0", features = ["bytes"] }
similar-asserts = "1.6.0"
similar-asserts = "1.6.1"
# Don't change sled's version on accident; sled's on-disk format is not yet
# stable and requires manual migrations. In the limit this won't matter because
# the upgrade system will replace the DNS server zones entirely, but while we
Expand Down Expand Up @@ -660,7 +660,7 @@ term = "0.7"
termios = "0.3"
termtree = "0.5.1"
textwrap = "0.16.1"
test-strategy = "0.3.1"
test-strategy = "0.4.0"
thiserror = "1.0"
tofino = { git = "https://github.com/oxidecomputer/tofino", branch = "main" }
tokio = "1.40.0"
Expand Down
1 change: 1 addition & 0 deletions clients/bootstrap-agent-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ uuid.workspace = true
omicron-uuid-kinds.workspace = true
omicron-workspace-hack.workspace = true
oxnet.workspace = true
semver.workspace = true
6 changes: 6 additions & 0 deletions clients/bootstrap-agent-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ progenitor::generate_api!(
ImportExportPolicy = omicron_common::api::external::ImportExportPolicy,
TypedUuidForRackInitKind = omicron_uuid_kinds::RackInitUuid,
TypedUuidForRackResetKind = omicron_uuid_kinds::RackResetUuid,
},
convert = {
{
type = "string",
pattern = r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$",
} = semver::Version,
}
);

Expand Down
1 change: 1 addition & 0 deletions clients/wicketd-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ progenitor.workspace = true
regress.workspace = true
reqwest = { workspace = true, features = ["rustls-tls", "stream"] }
schemars.workspace = true
semver.workspace = true
serde.workspace = true
serde_json.workspace = true
sled-agent-types.workspace = true
Expand Down
6 changes: 6 additions & 0 deletions clients/wicketd-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ progenitor::generate_api!(
UserSpecifiedImportExportPolicy = wicket_common::rack_setup::UserSpecifiedImportExportPolicy,
UserSpecifiedPortConfig = wicket_common::rack_setup::UserSpecifiedPortConfig,
UserSpecifiedRackNetworkConfig = wicket_common::rack_setup::UserSpecifiedRackNetworkConfig,
},
convert = {
{
type = "string",
pattern = r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$",
} = semver::Version,
}
);

Expand Down
11 changes: 11 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,15 @@ disallowed-methods = [
# Instead, the "transaction_retry_wrapper" should be preferred, as it
# automatically retries transactions experiencing contention.
{ path = "async_bb8_diesel::AsyncConnection::transaction_async", reason = "Prefer to use transaction_retry_wrapper, if possible. For tests and nested transactions, use transaction_non_retry_wrapper to at least get dtrace probes" },

# We use disallowed-methods for these rather than disallowed-types, because
# there's still one legitimate use for `once_cell`'s types:
# `get_or_try_init`, which isn't stablet yet.
# https://github.com/rust-lang/rust/issues/109737
{ path = "once_cell::unsync::OnceCell::get_or_init", reason = "use `std::cell::OnceCell` instead, unless you need get_or_try_init in which case #[expect] this lint" },
{ path = "once_cell::sync::OnceCell::get_or_init", reason = "use `std::sync::OnceLock` instead, unless you need get_or_try_init in which case #[expect] this lint" },
]
disallowed-types = [
{ path = "once_cell::unsync::Lazy", reason = "use `std::cell::LazyCell` instead" },
{ path = "once_cell::unsync::LazyCell", reason = "use `std::cell::LazyCell` instead" },
]
1 change: 0 additions & 1 deletion cockroach-admin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ http.workspace = true
illumos-utils.workspace = true
omicron-common.workspace = true
omicron-uuid-kinds.workspace = true
once_cell.workspace = true
# See omicron-rpaths for more about the "pq-sys" dependency.
pq-sys = "*"
schemars.workspace = true
Expand Down
3 changes: 1 addition & 2 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ oxnet.workspace = true
proptest = { workspace = true, optional = true }
rand.workspace = true
reqwest = { workspace = true, features = ["rustls-tls", "stream"] }
schemars = { workspace = true, features = ["chrono", "uuid1"] }
schemars = { workspace = true, features = ["chrono", "semver", "uuid1"] }
semver.workspace = true
serde.workspace = true
serde_human_bytes.workspace = true
Expand All @@ -49,7 +49,6 @@ uuid.workspace = true
parse-display.workspace = true
progenitor-client.workspace = true
omicron-workspace-hack.workspace = true
once_cell.workspace = true
regress.workspace = true

[dev-dependencies]
Expand Down
26 changes: 14 additions & 12 deletions common/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
use crate::api::external::{self, Error};
use crate::policy::INTERNAL_DNS_REDUNDANCY;
use ipnetwork::Ipv6Network;
use once_cell::sync::Lazy;
use oxnet::{Ipv4Net, Ipv6Net};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV6};
use std::{
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV6},
sync::LazyLock,
};

pub const AZ_PREFIX: u8 = 48;
pub const RACK_PREFIX: u8 = 56;
Expand Down Expand Up @@ -101,7 +103,7 @@ pub const NUM_SOURCE_NAT_PORTS: u16 = 1 << 14;
// prefix range (`fd00::/48`). See `random_vpc_ipv6_prefix`.
// Furthermore, all the below *_OPTE_IPV6_SUBNET constants are
// /64's within this prefix.
pub static SERVICE_VPC_IPV6_PREFIX: Lazy<Ipv6Net> = Lazy::new(|| {
pub static SERVICE_VPC_IPV6_PREFIX: LazyLock<Ipv6Net> = LazyLock::new(|| {
Ipv6Net::new(
Ipv6Addr::new(0xfd77, 0xe9d2, 0x9cd9, 0, 0, 0, 0, 0),
VPC_IPV6_PREFIX_LENGTH,
Expand All @@ -110,11 +112,11 @@ pub static SERVICE_VPC_IPV6_PREFIX: Lazy<Ipv6Net> = Lazy::new(|| {
});

/// The IPv4 subnet for External DNS OPTE ports.
pub static DNS_OPTE_IPV4_SUBNET: Lazy<Ipv4Net> =
Lazy::new(|| Ipv4Net::new(Ipv4Addr::new(172, 30, 1, 0), 24).unwrap());
pub static DNS_OPTE_IPV4_SUBNET: LazyLock<Ipv4Net> =
LazyLock::new(|| Ipv4Net::new(Ipv4Addr::new(172, 30, 1, 0), 24).unwrap());

/// The IPv6 subnet for External DNS OPTE ports.
pub static DNS_OPTE_IPV6_SUBNET: Lazy<Ipv6Net> = Lazy::new(|| {
pub static DNS_OPTE_IPV6_SUBNET: LazyLock<Ipv6Net> = LazyLock::new(|| {
Ipv6Net::new(
Ipv6Addr::new(0xfd77, 0xe9d2, 0x9cd9, 1, 0, 0, 0, 0),
VPC_SUBNET_IPV6_PREFIX_LENGTH,
Expand All @@ -123,11 +125,11 @@ pub static DNS_OPTE_IPV6_SUBNET: Lazy<Ipv6Net> = Lazy::new(|| {
});

/// The IPv4 subnet for Nexus OPTE ports.
pub static NEXUS_OPTE_IPV4_SUBNET: Lazy<Ipv4Net> =
Lazy::new(|| Ipv4Net::new(Ipv4Addr::new(172, 30, 2, 0), 24).unwrap());
pub static NEXUS_OPTE_IPV4_SUBNET: LazyLock<Ipv4Net> =
LazyLock::new(|| Ipv4Net::new(Ipv4Addr::new(172, 30, 2, 0), 24).unwrap());

/// The IPv6 subnet for Nexus OPTE ports.
pub static NEXUS_OPTE_IPV6_SUBNET: Lazy<Ipv6Net> = Lazy::new(|| {
pub static NEXUS_OPTE_IPV6_SUBNET: LazyLock<Ipv6Net> = LazyLock::new(|| {
Ipv6Net::new(
Ipv6Addr::new(0xfd77, 0xe9d2, 0x9cd9, 2, 0, 0, 0, 0),
VPC_SUBNET_IPV6_PREFIX_LENGTH,
Expand All @@ -136,11 +138,11 @@ pub static NEXUS_OPTE_IPV6_SUBNET: Lazy<Ipv6Net> = Lazy::new(|| {
});

/// The IPv4 subnet for Boundary NTP OPTE ports.
pub static NTP_OPTE_IPV4_SUBNET: Lazy<Ipv4Net> =
Lazy::new(|| Ipv4Net::new(Ipv4Addr::new(172, 30, 3, 0), 24).unwrap());
pub static NTP_OPTE_IPV4_SUBNET: LazyLock<Ipv4Net> =
LazyLock::new(|| Ipv4Net::new(Ipv4Addr::new(172, 30, 3, 0), 24).unwrap());

/// The IPv6 subnet for Boundary NTP OPTE ports.
pub static NTP_OPTE_IPV6_SUBNET: Lazy<Ipv6Net> = Lazy::new(|| {
pub static NTP_OPTE_IPV6_SUBNET: LazyLock<Ipv6Net> = LazyLock::new(|| {
Ipv6Net::new(
Ipv6Addr::new(0xfd77, 0xe9d2, 0x9cd9, 3, 0, 0, 0, 0),
VPC_SUBNET_IPV6_PREFIX_LENGTH,
Expand Down
113 changes: 14 additions & 99 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use parse_display::FromStr;
use rand::thread_rng;
use rand::Rng;
use schemars::JsonSchema;
use semver;
use semver::Version;
use serde::Deserialize;
use serde::Serialize;
use serde_with::{DeserializeFromStr, SerializeDisplay};
Expand Down Expand Up @@ -293,6 +293,12 @@ impl<'a> From<&'a Name> for &'a str {
}
}

impl From<Name> for String {
fn from(name: Name) -> Self {
name.0
}
}

/// `Name` instances are comparable like Strings, primarily so that they can
/// be used as keys in trees.
impl<S> PartialEq<S> for Name
Expand Down Expand Up @@ -488,56 +494,6 @@ fn name_schema(
.into()
}

// TODO: remove wrapper for semver::Version once this PR goes through
// https://github.com/GREsau/schemars/pull/195
#[derive(
Clone,
Debug,
Serialize,
Deserialize,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
Display,
FromStr,
)]
#[display("{0}")]
#[serde(transparent)]
pub struct SemverVersion(pub semver::Version);

impl SemverVersion {
pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
Self(semver::Version::new(major, minor, patch))
}

/// This is the official ECMAScript-compatible validation regex for
/// semver:
/// <https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string>
const VALIDATION_REGEX: &'static str = r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$";
}

impl JsonSchema for SemverVersion {
fn schema_name() -> String {
"SemverVersion".to_string()
}

fn json_schema(
_: &mut schemars::gen::SchemaGenerator,
) -> schemars::schema::Schema {
schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
string: Some(Box::new(schemars::schema::StringValidation {
pattern: Some(Self::VALIDATION_REGEX.to_owned()),
..Default::default()
})),
..Default::default()
}
.into()
}
}

/// Name for a built-in role
#[derive(
Clone,
Expand Down Expand Up @@ -3166,7 +3122,7 @@ pub struct TufRepoMeta {
pub valid_until: DateTime<Utc>,

/// The system version in artifacts.json.
pub system_version: SemverVersion,
pub system_version: Version,

/// The file name of the repository.
///
Expand Down Expand Up @@ -3263,7 +3219,6 @@ mod test {
use super::Generation;
use super::RouteDestination;
use super::RouteTarget;
use super::SemverVersion;
use super::VpcFirewallRuleHostFilter;
use super::VpcFirewallRuleTarget;
use super::{
Expand All @@ -3276,61 +3231,21 @@ mod test {
use crate::api::external::Error;
use crate::api::external::Hostname;
use crate::api::external::ResourceType;
use semver::Version;
use std::convert::TryFrom;
use std::str::FromStr;

#[test]
fn test_semver_validation() {
// Examples copied from
// https://github.com/dtolnay/semver/blob/cc2cfed67c17dfe6abae18726830bdb6d7cf740d/tests/test_version.rs#L13.
let valid = [
"1.2.3",
"1.2.3-alpha1",
"1.2.3+build5",
"1.2.3+5build",
"1.2.3-alpha1+build5",
"1.2.3-1.alpha1.9+build5.7.3aedf",
"1.2.3-0a.alpha1.9+05build.7.3aed",
"0.4.0-beta.1+0851523",
"1.1.0-beta-10",
];
let invalid = [
// These examples are rejected by the validation regex.
"",
"1",
"1.2",
"1.2.3-",
"a.b.c",
"1.2.3 abc",
"1.2.3-01",
];

let r = regress::Regex::new(SemverVersion::VALIDATION_REGEX)
.expect("validation regex is valid");
for input in valid {
let m = r
.find(input)
.unwrap_or_else(|| panic!("input {input} did not match regex"));
assert_eq!(m.start(), 0, "input {input} did not match start");
assert_eq!(m.end(), input.len(), "input {input} did not match end");
}

for input in invalid {
assert!(
r.find(input).is_none(),
"invalid input {input} should not match validation regex"
);
}
}

// This test originates from when we had a wrapper struct around
// `semver::Version`, but it's probably worth carrying this test that
// ensures the behavior we rely on is accurate.
#[test]
fn test_semver_serialize() {
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
struct MyStruct {
version: SemverVersion,
version: Version,
}

let v = MyStruct { version: SemverVersion::new(1, 2, 3) };
let v = MyStruct { version: Version::new(1, 2, 3) };
let expected = "{\"version\":\"1.2.3\"}";
assert_eq!(serde_json::to_string(&v).unwrap(), expected);
assert_eq!(serde_json::from_str::<MyStruct>(expected).unwrap(), v);
Expand Down
Loading

0 comments on commit cfb06bc

Please sign in to comment.