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
3 changes: 3 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion crates/admin-cli/src/machine/nvlink_info/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

use ::rpc::admin_cli::OutputFormat;
use ::rpc::forge as forgerpc;
use carbide_utils::none_if_empty::NoneIfEmpty;

use super::args::{NvlinkInfoArgs, NvlinkInfoPopulateArgs};
use crate::errors::{CarbideCliError, CarbideCliResult};
Expand Down Expand Up @@ -149,7 +150,7 @@ pub async fn handle_nvlink_info_populate(
.get("server_header")
.and_then(|h| h.get("domain_uuid"))
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())
.none_if_empty()
.ok_or_else(|| {
CarbideCliError::GenericError("No domain_uuid in NMX-C server_header".to_string())
})?
Expand Down
11 changes: 4 additions & 7 deletions crates/admin-cli/src/managed_switch/show/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use std::collections::HashMap;
use std::fmt::Write;

use carbide_utils::none_if_empty::NoneIfEmpty;
use carbide_uuid::switch::SwitchId;
use prettytable::{Cell, Row, Table};
use rpc::admin_cli::OutputFormat;
Expand Down Expand Up @@ -386,19 +387,19 @@ fn show_managed_switch_details_view(m: ManagedSwitchOutput) -> CarbideCliResult<
(" ID", m.switch_id),
(" Slot Number", m.slot_number.map(|n| n.to_string())),
(" Tray Index", m.tray_index.map(|n| n.to_string())),
(" Serial Number", non_empty(m.serial_number)),
(" Serial Number", m.serial_number.none_if_empty()),
(" Rack ID", m.rack_id),
(" Power State", m.power_state),
(" Health", m.health_status),
(
" NVOS MAC Addresses",
non_empty(m.nvos_mac_addresses.join(", ")),
m.nvos_mac_addresses.join(", ").none_if_empty(),
),
(" BMC", Some(String::new())),
(" Version", m.bmc_version),
(" Firmware Version", m.bmc_firmware_version),
(" IP", m.bmc_ip),
(" MAC", non_empty(m.bmc_mac)),
(" MAC", m.bmc_mac.none_if_empty()),
];

for (key, value) in data {
Expand All @@ -418,10 +419,6 @@ fn show_managed_switch_details_view(m: ManagedSwitchOutput) -> CarbideCliResult<
Ok(())
}

fn non_empty(s: String) -> Option<String> {
if s.is_empty() { None } else { Some(s) }
}

pub async fn handle_show(
output_file: &mut Box<dyn tokio::io::AsyncWrite + Unpin>,
args: Args,
Expand Down
3 changes: 2 additions & 1 deletion crates/admin-cli/src/site_explorer/get_report/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use ::rpc::admin_cli::OutputFormat;
use ::rpc::site_explorer::{
EndpointExplorationReport, ExploredEndpoint, ExploredManagedHost, SiteExplorationReport,
};
use carbide_utils::none_if_empty::NoneIfEmpty;
use prettytable::{Cell, Row, Table, format, row};

use super::args::Args;
Expand Down Expand Up @@ -484,7 +485,7 @@ fn endpoint_to_row(endpoint: &ExploredEndpoint) -> Row {
.map(|a| {
let mac = a.mac_address.as_deref().unwrap_or_default();
if a.interface_enabled() {
if let Some(ls) = a.link_status.as_deref().filter(|v| !v.is_empty()) {
if let Some(ls) = a.link_status.as_deref().none_if_empty() {
format!("{mac} [{}]", ls)
} else {
mac.to_string()
Expand Down
6 changes: 4 additions & 2 deletions crates/admin-cli/src/sku/bulk_update_metadata/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* limitations under the License.
*/

use carbide_utils::none_if_empty::NoneIfEmpty;

use super::super::update_metadata;
use super::args::Args;
use crate::errors::{CarbideCliError, CarbideCliResult};
Expand Down Expand Up @@ -43,8 +45,8 @@ pub async fn bulk_update_metadata(args: Args, api_client: &ApiClient) -> Carbide
tracing::error!("No SKU ID at line {current_line}");
continue;
};
let device_type = data.get(1).filter(|s| !s.is_empty()).map(str::to_owned);
let description = data.get(2).filter(|s| !s.is_empty()).map(str::to_owned);
let device_type = data.get(1).none_if_empty().map(str::to_owned);
let description = data.get(2).none_if_empty().map(str::to_owned);

// log errors but don't stop the processing
if let Err(e) = api_client
Expand Down
9 changes: 5 additions & 4 deletions crates/agent/src/astra_weave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use ::rpc::forge::{
AstraAttachmentStatus, AstraConfig, AstraConfigStatus, AstraPhase, AstraStatus,
SpxAttachmentType,
};
use carbide_utils::none_if_empty::NoneIfEmpty;
use eyre::WrapErr;

use crate::weave_ew_vpc_client::proto::state::Phase;
Expand Down Expand Up @@ -164,7 +165,7 @@ async fn create_weave_ew_vpc_virtual_networks(
.metadata
.as_ref()
.and_then(|metadata| metadata.id.clone())
.filter(|id| !id.is_empty());
.none_if_empty();
let state = virtual_network
.status
.as_ref()
Expand Down Expand Up @@ -323,7 +324,7 @@ async fn delete_stale_weave_ew_vpc_virtual_networks(
.metadata
.as_ref()
.and_then(|metadata| metadata.id.clone())
.filter(|id| !id.is_empty())
.none_if_empty()
else {
tracing::error!(
?virtual_network,
Expand Down Expand Up @@ -602,7 +603,7 @@ async fn delete_stale_weave_ew_vpc_astra_attachments(
.metadata
.as_ref()
.and_then(|metadata| metadata.id.clone())
.filter(|id| !id.is_empty())
.none_if_empty()
else {
tracing::error!(
?virtual_network_attachment,
Expand Down Expand Up @@ -668,7 +669,7 @@ pub async fn delete_match_attachment_with_vni_changed(
let Some(delete_attachment_id) = match_attachment
.and_then(|attachment| attachment.metadata.as_ref())
.and_then(|metadata| metadata.id.clone())
.filter(|id| !id.is_empty())
.none_if_empty()
else {
tracing::error!(
?match_attachment,
Expand Down
3 changes: 2 additions & 1 deletion crates/agent/src/dpu/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use std::fmt::Debug;
use std::net::IpAddr;
use std::path::PathBuf;

use carbide_utils::none_if_empty::NoneIfEmpty;
use eyre::WrapErr;
use ipnetwork::IpNetwork;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -225,7 +226,7 @@ impl Interface {
.copied()
.collect::<Vec<_>>();

if res.is_empty() { None } else { Some(res) }
res.none_if_empty()
}
}

Expand Down
9 changes: 5 additions & 4 deletions crates/agent/src/ethernet_virtualization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1937,6 +1937,7 @@ mod tests {
use ::rpc::{common as rpc_common, forge as rpc};
use carbide_network::virtualization::{VpcVirtualizationType, get_svi_ip};
use carbide_rpc_utils::dhcp::{DhcpConfig, HostConfig};
use carbide_utils::none_if_empty::NoneIfEmpty;
use eyre::WrapErr;
use ipnetwork::IpNetwork;

Expand Down Expand Up @@ -3863,26 +3864,26 @@ mod tests {
let interface_prefix_v6 = Some("2001:db8::/127".to_string());

let addresses: Vec<String> = std::iter::once(ip.clone())
.chain(ip6.filter(|s| !s.is_empty()))
.chain(ip6.none_if_empty())
.collect();
assert_eq!(addresses, vec!["10.0.0.1", "2001:db8::1"]);

let prefixes: Vec<String> = std::iter::once(interface_prefix)
.chain(interface_prefix_v6.filter(|s| !s.is_empty()))
.chain(interface_prefix_v6.none_if_empty())
.collect();
assert_eq!(prefixes, vec!["10.0.0.0/31", "2001:db8::/127"]);

// Verify empty ip6 is not included.
let empty_ip6: Option<String> = Some("".to_string());
let addresses2: Vec<String> = std::iter::once(ip)
.chain(empty_ip6.filter(|s| !s.is_empty()))
.chain(empty_ip6.none_if_empty())
.collect();
assert_eq!(addresses2, vec!["10.0.0.1"]);

// Verify None ip6 is not included.
let none_ip6: Option<String> = None;
let addresses3: Vec<String> = std::iter::once("10.0.0.1".to_string())
.chain(none_ip6.filter(|s| !s.is_empty()))
.chain(none_ip6.none_if_empty())
.collect();
assert_eq!(addresses3, vec!["10.0.0.1"]);
}
Expand Down
3 changes: 2 additions & 1 deletion crates/api-core/src/cfg/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use carbide_rack_controller::config::{RackValidationConfig, RmsConfig};
use carbide_site_explorer::config::SiteExplorerConfig;
use carbide_state_controller_common::config::StateControllerConfig;
use carbide_utils::config::{as_duration, as_option_duration, as_std_duration};
use carbide_utils::none_if_empty::NoneIfEmpty;
use chrono::Duration;
use db::host_naming::HostNamingStrategyKind;
use duration_str::{deserialize_duration, deserialize_duration_chrono};
Expand Down Expand Up @@ -2991,7 +2992,7 @@ impl TrafficInterceptBridging {
.join(",");

// An empty map, or one with only skipped entries, means no provisioning config.
(!config.is_empty()).then_some(config)
config.none_if_empty()
}
}

Expand Down
7 changes: 2 additions & 5 deletions crates/api-core/src/ethernet_virtualization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::net::{IpAddr, Ipv4Addr};

use ::rpc::forge as rpc;
use carbide_network::virtualization::{VpcVirtualizationType, get_svi_ip};
use carbide_utils::none_if_empty::NoneIfEmpty;
use carbide_uuid::instance::InstanceId;
use carbide_uuid::machine::{MachineId, MachineInterfaceId};
use carbide_uuid::network::NetworkSegmentId;
Expand Down Expand Up @@ -71,11 +72,7 @@ impl SiteFabricPrefixList {
// the VPC isolation feature built on top of it, and it is better not
// to construct one of these at all (and thus the Option-wrapped return
// type).
if prefixes.is_empty() {
None
} else {
Some(Self { prefixes })
}
prefixes.none_if_empty().map(|prefixes| Self { prefixes })
}

pub fn as_ip_slice(&self) -> &[IpNetwork] {
Expand Down
5 changes: 3 additions & 2 deletions crates/api-core/src/handlers/bmc_endpoint_explorer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::net::SocketAddr;
use ::rpc::forge as rpc;
use ::rpc::model::machine::machine_id::try_parse_machine_id;
use carbide_redfish::boot_interface::BootInterfaceTarget;
use carbide_utils::none_if_empty::NoneIfEmpty;
use carbide_uuid::machine::MachineId;
use db::WithTransaction;
use db::machine_interface::find_by_ip;
Expand Down Expand Up @@ -438,7 +439,7 @@ pub(crate) async fn machine_setup(
.boot_interface_mac
.as_deref()
.map(str::trim)
.filter(|m| !m.is_empty())
.none_if_empty()
.map(|m| m.parse::<MacAddress>())
.transpose()
.map_err(|e| CarbideError::InvalidArgument(format!("invalid boot_interface_mac: {e}")))?;
Expand Down Expand Up @@ -494,7 +495,7 @@ pub(crate) async fn set_dpu_first_boot_order(
.boot_interface_mac
.as_deref()
.map(str::trim)
.filter(|m| !m.is_empty())
.none_if_empty()
.map(|m| m.parse::<MacAddress>())
.transpose()
.map_err(|e| CarbideError::InvalidArgument(format!("invalid boot_interface_mac: {e}")))?;
Expand Down
3 changes: 2 additions & 1 deletion crates/api-core/src/handlers/component_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use carbide_rack::firmware_object::rms_access_token_or_noauth;
use carbide_secrets::credentials::{
BmcCredentialType, CredentialKey, CredentialManager, Credentials,
};
use carbide_utils::none_if_empty::NoneIfEmpty;
use carbide_uuid::machine::MachineId;
use carbide_uuid::power_shelf::PowerShelfId;
use carbide_uuid::rack::RackId;
Expand Down Expand Up @@ -976,7 +977,7 @@ async fn resolve_switch_endpoints(
nvos_mac,
bmc_credentials,
nvos_credentials,
nvos_host_name: row.nvos_hostname.filter(|hostname| !hostname.is_empty()),
nvos_host_name: row.nvos_hostname.none_if_empty(),
});
}

Expand Down
29 changes: 13 additions & 16 deletions crates/api-core/src/handlers/extension_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use ::rpc::errors::RpcDataConversionError;
use ::rpc::forge as rpc;
use carbide_secrets::credentials::{CredentialKey, Credentials};
use carbide_utils::none_if_empty::NoneIfEmpty;
use carbide_uuid::extension_service::ExtensionServiceId;
use config_version::ConfigVersion;
use db::{WithTransaction, extension_service, instance};
Expand Down Expand Up @@ -635,22 +636,18 @@ pub(crate) async fn get_versions_info(
let req = request.into_inner();

// Parse versions from strings to ConfigVersions
let versions: Option<Vec<ConfigVersion>> = if !req.versions.is_empty() {
let versions = req
.versions
.iter()
.map(|v| v.parse::<config_version::ConfigVersion>())
.collect::<Result<Vec<_>, _>>()
.map_err(|e| {
CarbideError::from(RpcDataConversionError::InvalidConfigVersion(format!(
"Failed to parse version: {}",
e
)))
})?;
Some(versions)
} else {
None
};
let versions: Option<Vec<ConfigVersion>> = req
.versions
.iter()
.map(|v| v.parse::<config_version::ConfigVersion>())
.collect::<Result<Vec<_>, _>>()
.map_err(|e| {
CarbideError::from(RpcDataConversionError::InvalidConfigVersion(format!(
"Failed to parse version: {}",
e
)))
})?
.none_if_empty();

let mut txn = api.txn_begin().await?;

Expand Down
3 changes: 2 additions & 1 deletion crates/api-core/src/handlers/machine_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::sync::Arc;
use std::sync::atomic::Ordering;

pub use ::rpc::forge as rpc;
use carbide_utils::none_if_empty::NoneIfEmpty;
use carbide_uuid::machine::MachineIdSource;
use carbide_uuid::nvlink::NvLinkDomainId;
use db::WithTransaction;
Expand Down Expand Up @@ -433,7 +434,7 @@ pub(crate) async fn discover_machine(
&& let Some(scout_version) = machine_discovery_info
.discovery_reporter_version
.as_deref()
.filter(|v| !v.is_empty())
.none_if_empty()
{
db::machine::update_last_scout_observed_version(
&stable_machine_id,
Expand Down
8 changes: 3 additions & 5 deletions crates/api-core/src/handlers/machine_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use ::rpc::forge::{
self as rpc, Jwks, JwksKind, JwksRequest, MachineIdentityResponse, OpenIdConfigRequest,
OpenIdConfiguration,
};
use carbide_utils::none_if_empty::NoneIfEmpty;
use carbide_uuid::machine::MachineId;
use chrono::Utc;
use db::{WithTransaction, tenant_identity_config};
Expand Down Expand Up @@ -211,14 +212,11 @@ pub(crate) async fn sign_machine_identity(
let now = Utc::now().timestamp();

if let (Some(token_endpoint), Some(subject_token_audience), Some(auth_method)) = (
identity_row
.token_endpoint
.as_deref()
.filter(|u| !u.is_empty()),
identity_row.token_endpoint.as_deref().none_if_empty(),
identity_row
.subject_token_audience
.as_deref()
.filter(|a| !a.is_empty()),
.none_if_empty(),
identity_row.auth_method,
) {
let subject_ttl = i64::from(identity_row.token_ttl_sec);
Expand Down
Loading
Loading