Skip to content
Merged
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
6 changes: 3 additions & 3 deletions crates/admin-cli/src/expected_rack/add/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::metadata::parse_rpc_labels;
pub struct Args {
#[clap(help = "Rack ID of the expected rack")]
pub rack_id: RackId,
#[clap(help = "Rack type of the expected rack")]
pub rack_type: String,
#[clap(help = "Rack profile ID of the expected rack")]
pub rack_profile_id: String,

#[clap(
long = "meta-name",
Expand Down Expand Up @@ -61,7 +61,7 @@ impl From<Args> for rpc::forge::ExpectedRack {
};
rpc::forge::ExpectedRack {
rack_id: Some(value.rack_id),
rack_type: value.rack_type,
rack_profile_id: Some(value.rack_profile_id.into()),
metadata: Some(metadata),
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/admin-cli/src/expected_rack/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
* limitations under the License.
*/

use carbide_uuid::rack::RackId;
use carbide_uuid::rack::{RackId, RackProfileId};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct ExpectedRackJson {
pub rack_id: RackId,
pub rack_type: String,
pub rack_profile_id: RackProfileId,
#[serde(default)]
pub metadata: Option<rpc::forge::Metadata>,
}
2 changes: 1 addition & 1 deletion crates/admin-cli/src/expected_rack/replace_all/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub async fn replace_all(args: Args, api_client: &ApiClient) -> CarbideCliResult
.into_iter()
.map(|rack| rpc_forge::ExpectedRack {
rack_id: Some(rack.rack_id),
rack_type: rack.rack_type,
rack_profile_id: Some(rack.rack_profile_id),
metadata: rack.metadata,
})
.collect(),
Expand Down
8 changes: 6 additions & 2 deletions crates/admin-cli/src/expected_rack/show/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn convert_and_print_into_nice_table(

table.set_titles(row![
"Rack ID",
"Rack Type",
"Rack Profile",
"Name",
"Description",
"Labels"
Expand Down Expand Up @@ -81,7 +81,11 @@ fn convert_and_print_into_nice_table(
.clone()
.map(|r| r.to_string())
.unwrap_or_default(),
expected_rack.rack_type,
expected_rack
.rack_profile_id
.as_ref()
.map(|id| id.to_string())
.unwrap_or_default(),
expected_rack
.metadata
.as_ref()
Expand Down
14 changes: 7 additions & 7 deletions crates/admin-cli/src/expected_rack/update/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use serde::{Deserialize, Serialize};
pub struct Args {
#[clap(help = "Rack ID of the expected rack")]
pub rack_id: RackId,
#[clap(long, help = "Rack type of the expected rack")]
pub rack_type: Option<String>,
#[clap(long, help = "Rack profile ID of the expected rack")]
pub rack_profile_id: Option<String>,

#[clap(
long = "meta-name",
Expand Down Expand Up @@ -54,13 +54,13 @@ impl TryFrom<Args> for rpc::forge::ExpectedRack {
type Error = CarbideCliError;

fn try_from(args: Args) -> Result<Self, Self::Error> {
// rack_type is required for update.
let rack_type = args
.rack_type
.ok_or_else(|| CarbideCliError::GenericError("rack_type is required".to_string()))?;
// rack_profile_id is required for update.
let rack_profile_id = args.rack_profile_id.ok_or_else(|| {
CarbideCliError::GenericError("rack_profile_id is required".to_string())
})?;
Ok(rpc::forge::ExpectedRack {
rack_id: Some(args.rack_id),
rack_type,
rack_profile_id: Some(rack_profile_id.into()),
metadata: Some(rpc::forge::Metadata {
name: args.meta_name.unwrap_or_default(),
description: args.meta_description.unwrap_or_default(),
Expand Down
2 changes: 1 addition & 1 deletion crates/admin-cli/src/expected_rack/update/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rpc::forge::ExpectedRack;
use super::args::Args;
use crate::rpc::ApiClient;

/// update updates an existing expected rack's rack_type and metadata.
/// update updates an existing expected rack's rack_profile_id and metadata.
pub async fn update(data: Args, api_client: &ApiClient) -> color_eyre::Result<()> {
let req: ExpectedRack = data.try_into()?;
api_client.0.update_expected_rack(req).await?;
Expand Down
6 changes: 3 additions & 3 deletions crates/admin-cli/src/rack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
* limitations under the License.
*/

pub mod capabilities;
mod delete;
mod list;
pub mod metadata;
pub mod profile;
mod show;

#[cfg(test)]
Expand All @@ -38,6 +38,6 @@ pub enum Cmd {
Delete(delete::Args),
#[clap(subcommand, about = "Edit Metadata associated with a Rack")]
Metadata(metadata::Args),
#[clap(subcommand, about = "Rack capabilities")]
Capabilities(capabilities::Args),
#[clap(subcommand, about = "Rack profile")]
Profile(profile::Args),
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ use super::show;

#[derive(Parser, Debug, Clone)]
pub enum Args {
#[clap(about = "Show rack capabilities for a given rack")]
#[clap(about = "Show rack profile for a given rack")]
Show(show::Args),
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Run for Args {
async fn run(self, ctx: &mut RuntimeContext) -> CarbideCliResult<()> {
match self {
Args::Show(args) => {
show::cmd::show_capabilities(&ctx.api_client, args, &ctx.config).await?;
show::cmd::show_profile(&ctx.api_client, args, &ctx.config).await?;
}
}
Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ use clap::Parser;

#[derive(Parser, Debug, Clone)]
pub struct Args {
#[clap(help = "Rack ID to get capabilities for")]
#[clap(help = "Rack ID to get profile for")]
pub rack_id: RackId,
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@
use color_eyre::Result;
use prettytable::{Table, row};
use rpc::admin_cli::OutputFormat;
use rpc::forge::GetRackCapabilitiesResponse;
use rpc::forge::GetRackProfileResponse;
use serde::Serialize;

use super::args::Args;
use crate::cfg::runtime::RuntimeConfig;
use crate::rpc::ApiClient;

#[derive(Serialize)]
struct CapabilitiesOutput {
struct ProfileOutput {
rack_id: String,
rack_type: String,
rack_profile_id: String,
rack_hardware_type: String,
rack_hardware_topology: String,
rack_hardware_class: String,
Expand All @@ -46,9 +46,10 @@ struct CapabilitiesOutput {
power_shelf_slot_ids: Vec<u32>,
}

impl From<&GetRackCapabilitiesResponse> for CapabilitiesOutput {
fn from(r: &GetRackCapabilitiesResponse) -> Self {
let capabilities = r.capabilities.as_ref();
impl From<&GetRackProfileResponse> for ProfileOutput {
fn from(r: &GetRackProfileResponse) -> Self {
let profile = r.profile.as_ref();
let capabilities = profile.and_then(|p| p.capabilities.as_ref());
let compute = capabilities.and_then(|c| c.compute.as_ref());
let switch = capabilities.and_then(|c| c.switch.as_ref());
let power_shelf = capabilities.and_then(|c| c.power_shelf.as_ref());
Expand All @@ -59,22 +60,26 @@ impl From<&GetRackCapabilitiesResponse> for CapabilitiesOutput {
.as_ref()
.map(|id| id.to_string())
.unwrap_or_default(),
rack_type: r.rack_type.clone(),
rack_hardware_type: capabilities
.and_then(|c| c.rack_hardware_type.as_ref())
rack_profile_id: r
.rack_profile_id
.as_ref()
.map(|id| id.to_string())
.unwrap_or_default(),
rack_hardware_type: profile
.and_then(|p| p.rack_hardware_type.as_ref())
.map(|t| t.value.clone())
.unwrap_or_else(|| "N/A".to_string()),
rack_hardware_topology: capabilities
.map(|c| {
rpc::forge::RackHardwareTopology::try_from(c.rack_hardware_topology)
rack_hardware_topology: profile
.map(|p| {
rpc::forge::RackHardwareTopology::try_from(p.rack_hardware_topology)
.unwrap_or_default()
.as_str_name()
.to_string()
})
.unwrap_or_else(|| "N/A".to_string()),
rack_hardware_class: capabilities
.map(|c| {
rpc::forge::RackHardwareClass::try_from(c.rack_hardware_class)
rack_hardware_class: profile
.map(|p| {
rpc::forge::RackHardwareClass::try_from(p.rack_hardware_class)
.unwrap_or_default()
.as_str_name()
.to_string()
Expand Down Expand Up @@ -108,14 +113,14 @@ impl From<&GetRackCapabilitiesResponse> for CapabilitiesOutput {
}
}

pub async fn show_capabilities(
pub async fn show_profile(
api_client: &ApiClient,
args: Args,
config: &RuntimeConfig,
) -> Result<()> {
let response = api_client.get_rack_capabilities(args.rack_id).await?;
let response = api_client.get_rack_profile(args.rack_id).await?;

let output = CapabilitiesOutput::from(&response);
let output = ProfileOutput::from(&response);
match config.format {
OutputFormat::Json => println!("{}", serde_json::to_string_pretty(&output)?),
OutputFormat::Yaml => println!("{}", serde_yaml::to_string(&output)?),
Expand All @@ -136,8 +141,9 @@ fn slot_ids_display(ids: &[u32]) -> String {
}
}

fn show_detail(r: &GetRackCapabilitiesResponse) {
let capabilities = r.capabilities.as_ref();
fn show_detail(r: &GetRackProfileResponse) {
let profile = r.profile.as_ref();
let capabilities = profile.and_then(|p| p.capabilities.as_ref());
let compute = capabilities.and_then(|c| c.compute.as_ref());
let switch = capabilities.and_then(|c| c.switch.as_ref());
let power_shelf = capabilities.and_then(|c| c.power_shelf.as_ref());
Expand All @@ -150,19 +156,25 @@ fn show_detail(r: &GetRackCapabilitiesResponse) {
.map(|id| id.to_string())
.unwrap_or_default()
]);
table.add_row(row!["Rack Type", r.rack_type]);
table.add_row(row![
"Rack Profile",
r.rack_profile_id
.as_ref()
.map(|id| id.to_string())
.unwrap_or_default()
]);
table.add_row(row![
"Hardware Type",
capabilities
.and_then(|c| c.rack_hardware_type.as_ref())
profile
.and_then(|p| p.rack_hardware_type.as_ref())
.map(|t| t.value.as_str())
.unwrap_or("N/A")
]);
table.add_row(row![
"Hardware Topology",
capabilities
profile
.map(
|c| rpc::forge::RackHardwareTopology::try_from(c.rack_hardware_topology)
|p| rpc::forge::RackHardwareTopology::try_from(p.rack_hardware_topology)
.unwrap_or_default()
.as_str_name()
.to_string()
Expand All @@ -171,9 +183,9 @@ fn show_detail(r: &GetRackCapabilitiesResponse) {
]);
table.add_row(row![
"Hardware Class",
capabilities
profile
.map(
|c| rpc::forge::RackHardwareClass::try_from(c.rack_hardware_class)
|p| rpc::forge::RackHardwareClass::try_from(p.rack_hardware_class)
.unwrap_or_default()
.as_str_name()
.to_string()
Expand Down
18 changes: 9 additions & 9 deletions crates/admin-cli/src/rack/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,24 @@ fn parse_delete_missing_identifier_fails() {
assert!(result.is_err(), "should fail without identifier");
}

// parse_capabilities_show ensures capabilities show parses with rack ID.
// parse_profile_show ensures profile show parses with rack ID.
#[test]
fn parse_capabilities_show() {
let cmd = Cmd::try_parse_from(["rack", "capabilities", "show", "rack-123"])
.expect("should parse capabilities show");
fn parse_profile_show() {
let cmd = Cmd::try_parse_from(["rack", "profile", "show", "rack-123"])
.expect("should parse profile show");

match cmd {
Cmd::Capabilities(capabilities::Args::Show(args)) => {
Cmd::Profile(profile::Args::Show(args)) => {
assert_eq!(args.rack_id, "rack-123".parse().unwrap());
}
_ => panic!("expected Capabilities(Show) variant"),
_ => panic!("expected Profile(Show) variant"),
}
}

// parse_capabilities_show_missing_rack_id_fails ensures capabilities
// parse_profile_show_missing_rack_id_fails ensures profile
// show fails without rack ID.
#[test]
fn parse_capabilities_show_missing_rack_id_fails() {
let result = Cmd::try_parse_from(["rack", "capabilities", "show"]);
fn parse_profile_show_missing_rack_id_fails() {
let result = Cmd::try_parse_from(["rack", "profile", "show"]);
assert!(result.is_err(), "should fail without rack_id");
}
6 changes: 3 additions & 3 deletions crates/admin-cli/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,13 @@ impl ApiClient {
Ok(racks)
}

pub async fn get_rack_capabilities(
pub async fn get_rack_profile(
&self,
rack_id: RackId,
) -> CarbideCliResult<rpc::GetRackCapabilitiesResponse> {
) -> CarbideCliResult<rpc::GetRackProfileResponse> {
Ok(self
.0
.get_rack_capabilities(rpc::GetRackCapabilitiesRequest {
.get_rack_profile(rpc::GetRackProfileRequest {
rack_id: Some(rack_id),
})
.await?)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- Add rack_profile_id as a proper column on the racks table.
ALTER TABLE racks ADD COLUMN rack_profile_id VARCHAR(256);

-- Backfill from the JSONB config column for existing racks (stored as rack_type).
UPDATE racks SET rack_profile_id = config->>'rack_type' WHERE config->>'rack_type' IS NOT NULL;

-- Rename the column on expected_racks too (was rack_type).
ALTER TABLE expected_racks RENAME COLUMN rack_type TO rack_profile_id;
Comment thread
chet marked this conversation as resolved.
10 changes: 5 additions & 5 deletions crates/api-db/src/expected_rack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ pub async fn find_all(txn: &mut PgConnection) -> DatabaseResult<Vec<ExpectedRack
/// create creates a new expected rack.
pub async fn create(txn: &mut PgConnection, rack: &ExpectedRack) -> DatabaseResult<ExpectedRack> {
let query = "INSERT INTO expected_racks
(rack_id, rack_type, metadata_name, metadata_description, metadata_labels)
(rack_id, rack_profile_id, metadata_name, metadata_description, metadata_labels)
VALUES
($1::varchar, $2::varchar, $3::varchar, $4::varchar, $5::jsonb) RETURNING *";

sqlx::query_as(query)
.bind(&rack.rack_id)
.bind(&rack.rack_type)
.bind(&rack.rack_profile_id)
.bind(&rack.metadata.name)
.bind(&rack.metadata.description)
.bind(sqlx::types::Json(&rack.metadata.labels))
Expand Down Expand Up @@ -100,12 +100,12 @@ pub async fn clear(txn: &mut PgConnection) -> Result<(), DatabaseError> {
.map_err(|err| DatabaseError::query(query, err))
}

/// update updates an existing expected rack's rack_type and metadata.
/// update updates an existing expected rack's rack_profile_id and metadata.
pub async fn update(txn: &mut PgConnection, rack: &ExpectedRack) -> DatabaseResult<()> {
let query = "UPDATE expected_racks SET rack_type=$1, metadata_name=$2, metadata_description=$3, metadata_labels=$4 WHERE rack_id=$5";
let query = "UPDATE expected_racks SET rack_profile_id=$1, metadata_name=$2, metadata_description=$3, metadata_labels=$4 WHERE rack_id=$5";

let result = sqlx::query(query)
.bind(&rack.rack_type)
.bind(&rack.rack_profile_id)
.bind(&rack.metadata.name)
.bind(&rack.metadata.description)
.bind(sqlx::types::Json(&rack.metadata.labels))
Expand Down
Loading
Loading