Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion crates/admin-cli/src/expected_machines/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,31 @@ use carbide_uuid::rack::RackId;
use mac_address::MacAddress;
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum ExpectedMachineIdJson {
String(String),
RpcUuid { value: String },
}

fn deserialize_optional_expected_machine_id<'de, D>(
deserializer: D,
) -> Result<Option<String>, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(
Option::<ExpectedMachineIdJson>::deserialize(deserializer)?.map(|id| match id {
ExpectedMachineIdJson::String(value) => value,
ExpectedMachineIdJson::RpcUuid { value } => value,
}),
)
}

/// JSON shape for `replace-all` and file-based `update` (field names match gRPC / API `ExpectedMachine`).
#[derive(Debug, Serialize, Deserialize)]
pub struct ExpectedMachineJson {
#[serde(default)]
#[serde(default, deserialize_with = "deserialize_optional_expected_machine_id")]
pub id: Option<String>,
pub bmc_mac_address: MacAddress,
pub bmc_username: String,
Expand Down
56 changes: 56 additions & 0 deletions crates/admin-cli/src/expected_machines/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use carbide_test_support::Outcome::*;
use carbide_test_support::scenarios;
use clap::{CommandFactory, Parser};

use super::common::ExpectedMachineJson;
use super::*;

// verify_cmd_structure runs a baseline clap debug_assert()
Expand Down Expand Up @@ -222,6 +223,61 @@ fn parse_replace_all() {
}
}

#[test]
fn expected_machine_json_accepts_missing_id() {
let machine: ExpectedMachineJson = serde_json::from_str(
r#"{
"bmc_mac_address": "00:11:22:33:44:55",
"bmc_username": "admin",
"bmc_password": "secret",
"chassis_serial_number": "SN123"
}"#,
)
.expect("expected machine without id should parse");

assert_eq!(machine.id, None);
}

#[test]
fn expected_machine_json_accepts_string_id() {
let machine: ExpectedMachineJson = serde_json::from_str(
r#"{
"id": "123e4567-e89b-12d3-a456-426614174000",
"bmc_mac_address": "00:11:22:33:44:55",
"bmc_username": "admin",
"bmc_password": "secret",
"chassis_serial_number": "SN123"
}"#,
)
.expect("expected machine with string id should parse");

assert_eq!(
machine.id.as_deref(),
Some("123e4567-e89b-12d3-a456-426614174000")
);
}

#[test]
fn expected_machine_json_accepts_rpc_uuid_id() {
let machine: ExpectedMachineJson = serde_json::from_str(
r#"{
"id": {
"value": "123e4567-e89b-12d3-a456-426614174000"
},
"bmc_mac_address": "00:11:22:33:44:55",
"bmc_username": "admin",
"bmc_password": "secret",
"chassis_serial_number": "SN123"
}"#,
)
.expect("expected machine with RPC UUID id should parse");

assert_eq!(
machine.id.as_deref(),
Some("123e4567-e89b-12d3-a456-426614174000")
);
}

// parse_erase ensures erase parses with no arguments.
#[test]
fn parse_erase() {
Expand Down