Skip to content

Commit c8449e2

Browse files
authored
Fix Zfs::get_values, add tests (#7748)
Fixes #7747
1 parent e0ca417 commit c8449e2

File tree

1 file changed

+47
-3
lines changed

1 file changed

+47
-3
lines changed

illumos-utils/src/zfs.rs

+47-3
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ enum GetValueErrorRaw {
102102
#[error(transparent)]
103103
Execution(#[from] crate::ExecutionError),
104104

105+
#[error("Invalid property value 'all'")]
106+
InvalidValueAll,
107+
105108
#[error("No value found with that name")]
106109
MissingValue,
107110
}
@@ -843,13 +846,24 @@ impl Zfs {
843846
source: Option<PropertySource>,
844847
) -> Result<[String; N], GetValueError> {
845848
let mut cmd = std::process::Command::new(PFEXEC);
846-
let all_names =
847-
names.into_iter().map(|n| *n).collect::<Vec<&str>>().join(",");
849+
let all_names = names
850+
.into_iter()
851+
.map(|n| match *n {
852+
"all" => Err(GetValueError {
853+
filesystem: filesystem_name.to_string(),
854+
name: "all".to_string(),
855+
err: GetValueErrorRaw::InvalidValueAll,
856+
}),
857+
n => Ok(n),
858+
})
859+
.collect::<Result<Vec<&str>, GetValueError>>()?
860+
.join(",");
848861

849-
cmd.args(&[ZFS, "get", "-Ho", "value", &all_names]);
862+
cmd.args(&[ZFS, "get", "-Ho", "value"]);
850863
if let Some(source) = source {
851864
cmd.args(&["-s", &source.to_string()]);
852865
}
866+
cmd.arg(&all_names);
853867
cmd.arg(filesystem_name);
854868
let output = execute(&mut cmd).map_err(|err| GetValueError {
855869
filesystem: filesystem_name.to_string(),
@@ -940,6 +954,36 @@ pub fn get_all_omicron_datasets_for_delete() -> anyhow::Result<Vec<String>> {
940954
mod test {
941955
use super::*;
942956

957+
// This test validates that "get_values" at least parses correctly.
958+
//
959+
// To minimize test setup, we rely on a zfs dataset named "rpool" existing,
960+
// but do not modify it within this test.
961+
#[cfg(target_os = "illumos")]
962+
#[test]
963+
fn get_values_of_rpool() {
964+
// If the rpool exists, it should have a name.
965+
let values = Zfs::get_values("rpool", &["name"; 1], None)
966+
.expect("Failed to query rpool type");
967+
assert_eq!(values[0], "rpool");
968+
969+
// We don't really care if any local properties are set, we just don't
970+
// want this to throw an error.
971+
let _values =
972+
Zfs::get_values("rpool", &["name"; 1], Some(PropertySource::Local))
973+
.expect("Failed to query rpool type");
974+
975+
// Also, the "all" property should not be queryable. It's normally fine
976+
// to pass this value, it just returns a variable number of properties,
977+
// which doesn't work with the current implementation's parsing.
978+
let err = Zfs::get_values("rpool", &["all"; 1], None)
979+
.expect_err("Should not be able to query for 'all' property");
980+
981+
assert!(
982+
matches!(err.err, GetValueErrorRaw::InvalidValueAll),
983+
"Unexpected error: {err}"
984+
);
985+
}
986+
943987
#[test]
944988
fn parse_dataset_props() {
945989
let input = "dataset_name\tavailable\t1234\t-\n\

0 commit comments

Comments
 (0)