Skip to content

Commit

Permalink
WIP: abandoned mockall
Browse files Browse the repository at this point in the history
  • Loading branch information
davepacheco committed Feb 1, 2024
1 parent 1bc9e37 commit a28dc53
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 27 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

8 changes: 8 additions & 0 deletions nexus/blueprint-execution/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name = "nexus-blueprint-execution"
version = "0.1.0"
edition = "2021"

[build-dependencies]
omicron-rpaths.workspace = true

[dependencies]
anyhow.workspace = true
futures.workspace = true
Expand All @@ -13,6 +16,11 @@ sled-agent-client.workspace = true
slog.workspace = true
uuid.workspace = true

# See omicron-rpaths for more about the "pq-sys" dependency. This is needed
# because we use the database in the test suite, though it doesn't appear to
# work to put the pq-sys dependency only in dev-dependencies.
pq-sys = "*"

omicron-workspace-hack.workspace = true

[dev-dependencies]
Expand Down
10 changes: 10 additions & 0 deletions nexus/blueprint-execution/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

// See omicron-rpaths for documentation.
// NOTE: This file MUST be kept in sync with the other build.rs files in this
// repository.
fn main() {
omicron_rpaths::configure_default_omicron_rpaths();
}
33 changes: 14 additions & 19 deletions nexus/blueprint-execution/src/omicron_zones.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,6 @@ async fn sled_client(
))
}

/// Returns an example set of Omicron zones for testing
pub fn example_minimal(generation: Generation) -> OmicronZonesConfig {
OmicronZonesConfig {
generation,
zones: vec![OmicronZoneConfig {
id: Uuid::new_v4(),
underlay_address: "::1".parse().unwrap(),
zone_type: OmicronZoneType::InternalDns {
dataset,
dns_address: "oh-hello-internal-dns".into(),
gz_address: "::1".parse().unwrap(),
gz_address_index: 0,
http_address: "some-ipv6-address".into(),
},
}],
};
}

#[cfg(test)]
mod test {
use super::deploy_zones;
Expand Down Expand Up @@ -228,7 +210,20 @@ mod test {
// Zones are updated in a particular order, but each request contains
// the full set of zones that must be running.
// See `rack_setup::service::ServiceInner::run` for more details.
let mut zones = example_minimal();
let mut zones = OmicronZonesConfig {
generation,
zones: vec![OmicronZoneConfig {
id: Uuid::new_v4(),
underlay_address: "::1".parse().unwrap(),
zone_type: OmicronZoneType::InternalDns {
dataset,
dns_address: "oh-hello-internal-dns".into(),
gz_address: "::1".parse().unwrap(),
gz_address_index: 0,
http_address: "some-ipv6-address".into(),
},
}],
};

// Create a blueprint with only the `InternalDns` zone for both servers
// We reuse the same `OmicronZonesConfig` because the details don't
Expand Down
1 change: 1 addition & 0 deletions nexus/blueprint-execution/tests/config.test.toml
61 changes: 53 additions & 8 deletions nexus/src/app/background/blueprint_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use tokio::sync::watch;
pub struct BlueprintExecutor {
datastore: Arc<DataStore>,
rx_blueprint: watch::Receiver<Option<Arc<(BlueprintTarget, Blueprint)>>>,
exec_impl: Box<dyn BlueprintExecutorImpl>,
}

impl BlueprintExecutor {
Expand All @@ -28,7 +29,17 @@ impl BlueprintExecutor {
Option<Arc<(BlueprintTarget, Blueprint)>>,
>,
) -> BlueprintExecutor {
BlueprintExecutor { datastore, rx_blueprint }
Self::new_using_impl(datastore, rx_blueprint, Box::new(RealExecutor))
}

fn new_using_impl(
datastore: Arc<DataStore>,
rx_blueprint: watch::Receiver<
Option<Arc<(BlueprintTarget, Blueprint)>>,
>,
exec_impl: Box<dyn BlueprintExecutorImpl>,
) -> BlueprintExecutor {
BlueprintExecutor { datastore, rx_blueprint, exec_impl }
}
}

Expand Down Expand Up @@ -61,12 +72,10 @@ impl BackgroundTask for BlueprintExecutor {
});
}

let result = nexus_blueprint_execution::realize_blueprint(
opctx,
&self.datastore,
blueprint,
)
.await;
let result = self
.exec_impl
.realize_blueprint(opctx, &self.datastore, blueprint)
.await;

// Return the result as a `serde_json::Value`
match result {
Expand All @@ -87,13 +96,43 @@ impl BackgroundTask for BlueprintExecutor {
}
}

/// Abstraction over the underlying "realize_blueprint" behavior solely so that
/// we can provide a different implementation for testing
#[cfg_attr(test, mockall::automock)]
trait BlueprintExecutorImpl: Send + Sync {
fn realize_blueprint<'a>(
&self,
opctx: &'a OpContext,
datastore: &'a DataStore,
blueprint: &'a Blueprint,
) -> BoxFuture<'a, Result<(), Vec<anyhow::Error>>>;
}

/// Impls `BlueprintExecutorImpl` using the real implementation in
/// the `nexus_blueprint_execution` crate.
struct RealExecutor;
impl BlueprintExecutorImpl for RealExecutor {
fn realize_blueprint<'a>(
&self,
opctx: &'a OpContext,
datastore: &'a DataStore,
blueprint: &'a Blueprint,
) -> BoxFuture<'a, Result<(), Vec<anyhow::Error>>> {
nexus_blueprint_execution::realize_blueprint(
opctx, datastore, blueprint,
)
.boxed()
}
}

#[cfg(test)]
mod test {
use super::BlueprintExecutor;
use crate::app::background::common::BackgroundTask;
use httptest::matchers::{all_of, json_decoded, request};
use httptest::responders::status_code;
use httptest::Expectation;
use mockall::mock;
use nexus_db_model::{
ByteCount, SledBaseboard, SledSystemHardware, SledUpdate,
};
Expand Down Expand Up @@ -141,6 +180,7 @@ mod test {

#[nexus_test(server = crate::Server)]
async fn test_deploy_omicron_zones(cptestctx: &ControlPlaneTestContext) {
// XXX do we need the whole shebang?
let nexus = &cptestctx.server.apictx().nexus;
let datastore = nexus.datastore();
let opctx = OpContext::for_tests(
Expand All @@ -149,7 +189,12 @@ mod test {
);

let (blueprint_tx, blueprint_rx) = watch::channel(None);
let mut task = BlueprintExecutor::new(datastore.clone(), blueprint_rx);
let mock = MockBlueprintExecutorImpl::new();
let mut task = BlueprintExecutor::new_with_impl(
datastore.clone(),
blueprint_rx,
Box::new(mock),
);

// With no blueprint we should fail with an appropriate message.
let value = task.activate(&opctx).await;
Expand Down

0 comments on commit a28dc53

Please sign in to comment.