Skip to content

Commit

Permalink
[spr] changes introduced through rebase
Browse files Browse the repository at this point in the history
Created using spr 1.3.6-beta.1

[skip ci]
  • Loading branch information
papertigers committed Dec 13, 2024
2 parents 06e86e0 + 7e7c3bb commit d9b094b
Show file tree
Hide file tree
Showing 65 changed files with 5,254 additions and 3,164 deletions.
316 changes: 168 additions & 148 deletions Cargo.lock

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,10 @@ cookie = "0.18"
criterion = { version = "0.5.1", features = [ "async_tokio" ] }
crossbeam = "0.8"
crossterm = { version = "0.28.1", features = ["event-stream"] }
crucible-agent-client = { git = "https://github.com/oxidecomputer/crucible", rev = "2cfc7e0c8572b3bfafbfc838c4e6d658f442d239" }
crucible-pantry-client = { git = "https://github.com/oxidecomputer/crucible", rev = "2cfc7e0c8572b3bfafbfc838c4e6d658f442d239" }
crucible-smf = { git = "https://github.com/oxidecomputer/crucible", rev = "2cfc7e0c8572b3bfafbfc838c4e6d658f442d239" }
crucible-common = { git = "https://github.com/oxidecomputer/crucible", rev = "2cfc7e0c8572b3bfafbfc838c4e6d658f442d239" }
crucible-agent-client = { git = "https://github.com/oxidecomputer/crucible", rev = "5a41b826171c7d2a8412fa833377ab1df25ee8ec" }
crucible-pantry-client = { git = "https://github.com/oxidecomputer/crucible", rev = "5a41b826171c7d2a8412fa833377ab1df25ee8ec" }
crucible-smf = { git = "https://github.com/oxidecomputer/crucible", rev = "5a41b826171c7d2a8412fa833377ab1df25ee8ec" }
crucible-common = { git = "https://github.com/oxidecomputer/crucible", rev = "5a41b826171c7d2a8412fa833377ab1df25ee8ec" }
csv = "1.3.0"
curve25519-dalek = "4"
datatest-stable = "0.2.9"
Expand All @@ -363,7 +363,7 @@ derive_more = "0.99.18"
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.3.0"
diesel-dtrace = "0.4.0"
dns-server = { path = "dns-server" }
dns-server-api = { path = "dns-server-api" }
dns-service-client = { path = "clients/dns-service-client" }
Expand Down Expand Up @@ -494,7 +494,7 @@ omicron-test-utils = { path = "test-utils" }
omicron-workspace-hack = "0.1.0"
omicron-zone-package = "0.11.1"
oxide-client = { path = "clients/oxide-client" }
oxide-vpc = { git = "https://github.com/oxidecomputer/opte", rev = "98247c27846133a80fdb8f730f0c57e72d766561", features = [ "api", "std" ] }
oxide-vpc = { git = "https://github.com/oxidecomputer/opte", rev = "b56afeeb14e0042cbd7bda85b166ed86ee17820e", features = [ "api", "std" ] }
oxlog = { path = "dev-tools/oxlog" }
oxnet = { git = "https://github.com/oxidecomputer/oxnet" }
once_cell = "1.20.2"
Expand All @@ -504,7 +504,7 @@ openapiv3 = "2.0.0"
# must match samael's crate!
openssl = "0.10"
openssl-sys = "0.9"
opte-ioctl = { git = "https://github.com/oxidecomputer/opte", rev = "98247c27846133a80fdb8f730f0c57e72d766561" }
opte-ioctl = { git = "https://github.com/oxidecomputer/opte", rev = "b56afeeb14e0042cbd7bda85b166ed86ee17820e" }
oso = "0.27"
owo-colors = "4.1.0"
oximeter = { path = "oximeter/oximeter" }
Expand Down Expand Up @@ -541,10 +541,10 @@ prettyplease = { version = "0.2.25", features = ["verbatim"] }
proc-macro2 = "1.0"
progenitor = "0.8.0"
progenitor-client = "0.8.0"
bhyve_api = { git = "https://github.com/oxidecomputer/propolis", rev = "6936f1a949d155da38d3148abd42caef337dea04" }
propolis_api_types = { git = "https://github.com/oxidecomputer/propolis", rev = "6936f1a949d155da38d3148abd42caef337dea04" }
propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "6936f1a949d155da38d3148abd42caef337dea04" }
propolis-mock-server = { git = "https://github.com/oxidecomputer/propolis", rev = "6936f1a949d155da38d3148abd42caef337dea04" }
bhyve_api = { git = "https://github.com/oxidecomputer/propolis", rev = "220a6f367c18f2452dbc4fa9086f3fe73b961739" }
propolis_api_types = { git = "https://github.com/oxidecomputer/propolis", rev = "220a6f367c18f2452dbc4fa9086f3fe73b961739" }
propolis-client = { git = "https://github.com/oxidecomputer/propolis", rev = "220a6f367c18f2452dbc4fa9086f3fe73b961739" }
propolis-mock-server = { git = "https://github.com/oxidecomputer/propolis", rev = "220a6f367c18f2452dbc4fa9086f3fe73b961739" }
proptest = "1.5.0"
qorb = "0.2.1"
quote = "1.0"
Expand Down
6 changes: 6 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ disallowed-methods = [
# `IncompleteOnConflictExt::as_partial_index` in `nexus-db-queries`.
# See the documentation of that method for more.
"diesel::upsert::DecoratableTarget::filter_target",

# This form of transaction is susceptible to serialization failures,
# and can fail spuriously.
# 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. Feel free to override this for tests and nested transactions." },
]
1 change: 1 addition & 0 deletions common/src/api/internal/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,7 @@ pub struct ExternalIpGatewayMap {

/// Describes the purpose of the dataset.
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, EnumCount)]
#[cfg_attr(feature = "testing", derive(test_strategy::Arbitrary))]
pub enum DatasetKind {
// Durable datasets for zones
Cockroach,
Expand Down
4 changes: 4 additions & 0 deletions common/src/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ impl DatasetName {
Self { pool_name, kind }
}

pub fn into_parts(self) -> (ZpoolName, DatasetKind) {
(self.pool_name, self.kind)
}

pub fn pool(&self) -> &ZpoolName {
&self.pool_name
}
Expand Down
10 changes: 10 additions & 0 deletions dev-tools/clickhouse-cluster-dev/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ use std::time::Duration;
async fn main() -> Result<()> {
let request_timeout = Duration::from_secs(15);
let (logctx, path) = default_clickhouse_log_ctx_and_path();

if path.exists() {
let deployment =
default_clickhouse_cluster_test_deployment(path.clone());
slog::info!(logctx.log, "Stopping test clickhouse nodes");
deployment.teardown()?;
slog::info!(logctx.log, "Removing previous temporary test directory");
std::fs::remove_dir_all(&path)?;
}

std::fs::create_dir(&path)?;

slog::info!(logctx.log, "Setting up a ClickHouse cluster");
Expand Down
2 changes: 2 additions & 0 deletions dev-tools/omdb/src/bin/omdb/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// NOTE: emanates from Tabled macros
#![allow(clippy::useless_vec)]
// NOTE: allowing "transaction_async" without retry
#![allow(clippy::disallowed_methods)]

use crate::check_allow_destructive::DestructiveOperationToken;
use crate::helpers::const_max_len;
Expand Down
187 changes: 185 additions & 2 deletions dev-tools/omdb/src/bin/omdb/oximeter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
use crate::helpers::CONNECTION_OPTIONS_HEADING;
use crate::Omdb;
use anyhow::Context;
use chrono::SecondsFormat;
use clap::Args;
use clap::Subcommand;
use futures::TryStreamExt;
use internal_dns_types::names::ServiceName;
use oximeter_client::types::FailedCollection;
use oximeter_client::types::ProducerDetails;
use oximeter_client::types::ProducerEndpoint;
use oximeter_client::types::SuccessfulCollection;
use oximeter_client::Client;
use slog::Logger;
use std::net::SocketAddr;
Expand Down Expand Up @@ -41,6 +45,11 @@ pub struct OximeterArgs {
enum OximeterCommands {
/// List the producers the collector is assigned to poll.
ListProducers,
/// Fetch details about a single assigned producer.
ProducerDetails {
/// The ID of the producer to fetch.
producer_id: Uuid,
},
}

impl OximeterArgs {
Expand Down Expand Up @@ -81,9 +90,26 @@ impl OximeterArgs {
OximeterCommands::ListProducers => {
self.list_producers(client).await
}
OximeterCommands::ProducerDetails { producer_id } => {
self.producer_details(client, producer_id).await
}
}
}

async fn producer_details(
&self,
client: Client,
producer_id: Uuid,
) -> anyhow::Result<()> {
let details = client
.producer_details(&producer_id)
.await
.context("failed to fetch producer details")?
.into_inner();
print_producer_details(details);
Ok(())
}

async fn list_producers(&self, client: Client) -> anyhow::Result<()> {
let info = client
.collector_info()
Expand Down Expand Up @@ -120,11 +146,168 @@ struct Producer {

impl From<ProducerEndpoint> for Producer {
fn from(p: ProducerEndpoint) -> Self {
let interval = Duration::new(p.interval.secs, p.interval.nanos);
Self {
id: p.id,
address: p.address.parse().unwrap(),
interval: humantime::format_duration(interval).to_string(),
interval: duration_to_humantime(&p.interval),
}
}
}

fn duration_to_humantime(d: &oximeter_client::types::Duration) -> String {
let interval = Duration::new(d.secs, d.nanos);
humantime::format_duration(interval).to_string()
}

const WIDTH: usize = 12;

fn print_producer_details(details: ProducerDetails) {
println!();
println!("{:>WIDTH$}: {}", "ID", details.id);
println!("{:>WIDTH$}: {}", "Address", details.address);
println!(
"{:>WIDTH$}: {}",
"Registered",
details.registered.to_rfc3339_opts(SecondsFormat::Millis, true)
);
println!(
"{:>WIDTH$}: {}",
"Updated",
details.updated.to_rfc3339_opts(SecondsFormat::Millis, true)
);
println!(
"{:>WIDTH$}: {}",
"Interval",
duration_to_humantime(&details.interval)
);
println!("{:>WIDTH$}: {}", "Successes", details.n_collections);
println!("{:>WIDTH$}: {}", "Failures", details.n_failures);
println!();
print_last_success(details.last_success.as_ref());
println!();
print_last_failure(details.last_failure.as_ref());
}

fn print_last_success(maybe_success: Option<&SuccessfulCollection>) {
print!("{:>WIDTH$}: ", "Last success");
match maybe_success {
None => println!("None"),
Some(success) => {
println!();
println!(
"{:>WIDTH$}: {}",
"Started at",
success.started_at.to_rfc3339_opts(SecondsFormat::Millis, true)
);
println!(
"{:>WIDTH$}: {:?}",
"Queued for",
Duration::new(
success.time_queued.secs,
success.time_queued.nanos
)
);
println!(
"{:>WIDTH$}: {:?}",
"Duration",
Duration::new(
success.time_collecting.secs,
success.time_collecting.nanos
)
);
println!("{:>WIDTH$}: {}", "Samples", success.n_samples);
}
}
}

fn print_last_failure(maybe_failure: Option<&FailedCollection>) {
print!("{:>WIDTH$}: ", "Last failure");
match maybe_failure {
None => println!("None"),
Some(failure) => {
println!();
println!(
"{:>WIDTH$}: {}",
"Started at",
failure.started_at.to_rfc3339_opts(SecondsFormat::Millis, true)
);
println!(
"{:>WIDTH$}: {:?}",
"Queued for",
Duration::new(
failure.time_queued.secs,
failure.time_queued.nanos
)
);
println!(
"{:>WIDTH$}: {:?}",
"Duration",
Duration::new(
failure.time_collecting.secs,
failure.time_collecting.nanos
)
);
println!("{:>WIDTH$}: {}", "Reason", failure.reason);
}
}
}

#[cfg(test)]
mod tests {
use super::print_producer_details;
use chrono::Utc;
use oximeter_client::types::FailedCollection;
use oximeter_client::types::ProducerDetails;
use oximeter_client::types::SuccessfulCollection;
use std::time::Duration;
use uuid::Uuid;

#[test]
fn test_print_producer_details_success_only() {
let now = Utc::now();
let details = ProducerDetails {
id: Uuid::new_v4(),
address: "[::1]:12345".parse().unwrap(),
interval: Duration::from_secs(10).into(),
last_success: Some(SuccessfulCollection {
n_samples: 100,
started_at: now,
time_collecting: Duration::from_millis(100).into(),
time_queued: Duration::from_millis(10).into(),
}),
last_failure: None,
n_collections: 1,
n_failures: 0,
registered: now,
updated: now,
};
print_producer_details(details);
}

#[test]
fn test_print_producer_details_with_failure() {
let now = Utc::now();
let details = ProducerDetails {
id: Uuid::new_v4(),
interval: Duration::from_secs(10).into(),
address: "[::1]:12345".parse().unwrap(),
last_success: Some(SuccessfulCollection {
n_samples: 100,
started_at: now,
time_collecting: Duration::from_millis(100).into(),
time_queued: Duration::from_millis(10).into(),
}),
last_failure: Some(FailedCollection {
started_at: now,
time_collecting: Duration::from_millis(100).into(),
time_queued: Duration::from_millis(10).into(),
reason: String::from("unreachable"),
}),
n_collections: 1,
n_failures: 1,
registered: now,
updated: now,
};
print_producer_details(details);
}
}
5 changes: 3 additions & 2 deletions dev-tools/omdb/tests/usage_errors.out
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,9 @@ Query oximeter collector state
Usage: omdb oximeter [OPTIONS] <COMMAND>

Commands:
list-producers List the producers the collector is assigned to poll
help Print this message or the help of the given subcommand(s)
list-producers List the producers the collector is assigned to poll
producer-details Fetch details about a single assigned producer
help Print this message or the help of the given subcommand(s)

Options:
--log-level <LOG_LEVEL> log level filter [env: LOG_LEVEL=] [default: warn]
Expand Down
Loading

0 comments on commit d9b094b

Please sign in to comment.