nimbus_cli/output/
features.rsuse std::path::Path;
use anyhow::Result;
use nimbus_fml::intermediate_representation::FeatureManifest;
use serde_json::Value;
use crate::{
sources::{ExperimentSource, ManifestSource},
value_utils::{self, CliUtils},
};
impl ManifestSource {
pub(crate) fn print_defaults<P>(
&self,
feature_id: Option<&String>,
output: Option<P>,
) -> Result<bool>
where
P: AsRef<Path>,
{
let manifest: FeatureManifest = self.try_into()?;
let json = self.get_defaults_json(&manifest, feature_id)?;
value_utils::write_to_file_or_print(output, &json)?;
Ok(true)
}
fn get_defaults_json(
&self,
fm: &FeatureManifest,
feature_id: Option<&String>,
) -> Result<Value> {
Ok(match feature_id {
Some(id) => {
let (_, feature) = fm.find_feature(id).ok_or_else(|| {
anyhow::Error::msg(format!("Feature '{id}' does not exist in this manifest"))
})?;
feature.default_json()
}
_ => fm.default_json(),
})
}
}
impl ExperimentSource {
#[allow(clippy::too_many_arguments)]
pub(crate) fn print_features<P>(
&self,
branch: &String,
manifest_source: &ManifestSource,
feature_id: Option<&String>,
validate: bool,
multi: bool,
output: Option<P>,
) -> Result<bool>
where
P: AsRef<Path>,
{
let json = self.get_features_json(manifest_source, feature_id, branch, validate, multi)?;
value_utils::write_to_file_or_print(output, &json)?;
Ok(true)
}
fn get_features_json(
&self,
manifest_source: &ManifestSource,
feature_id: Option<&String>,
branch: &String,
validate: bool,
multi: bool,
) -> Result<Value> {
let value = self.try_into()?;
let branches = value_utils::try_find_branches_from_experiment(&value)?;
let b = branches
.iter()
.find(|b| b.get_str("slug").unwrap() == branch)
.ok_or_else(|| anyhow::format_err!("Branch '{branch}' does not exist"))?;
let feature_values = value_utils::try_find_features_from_branch(b)?;
let mut result = serde_json::value::Map::new();
for f in feature_values {
let id = f.get_str("featureId")?;
let value = f
.get("value")
.ok_or_else(|| anyhow::format_err!("Branch {branch} feature {id} has no value"))?;
match feature_id {
None => {
result.insert(id.to_string(), value.clone());
}
Some(feature_id) if feature_id == id => {
result.insert(id.to_string(), value.clone());
}
_ => continue,
}
}
if validate {
let fm: FeatureManifest = manifest_source.try_into()?;
let mut new = serde_json::value::Map::new();
for (id, value) in result {
let def = fm.validate_feature_config(&id, value)?;
new.insert(id.to_owned(), def.default_json());
}
result = new;
}
Ok(if !multi && result.len() == 1 {
match (result.values().find(|_| true), feature_id) {
(Some(v), _) => v.to_owned(),
(_, Some(id)) => anyhow::bail!(
"The '{id}' feature is not involved in '{branch}' branch of '{self}'"
),
(_, _) => {
anyhow::bail!("No features available in '{branch}' branch of '{self}'")
}
}
} else {
Value::Object(result)
})
}
}