in guard/src/rules/evaluate.rs [781:838]
fn evaluate<'s>(&self, context: &'s PathAwareValue, var_resolver: &'s dyn EvaluationContext) -> Result<Status> {
let mut type_report = AutoReport::new(
EvaluationType::Type,
var_resolver,
&self.type_name
);
if let Some(conditions) = &self.conditions {
let mut type_conds = AutoReport::new(
EvaluationType::Condition,
var_resolver,
""
);
match type_conds.status(conditions.evaluate(context, var_resolver)?).get_status() {
Status::PASS => {},
_ => {
return Ok(type_report.status(Status::SKIP).get_status())
}
}
}
let query = format!("Resources.*[ Type == \"{}\" ]", self.type_name);
let cfn_query = AccessQuery::try_from(query.as_str())?;
let values = match context.select(cfn_query.match_all, &cfn_query.query, var_resolver) {
Ok(v) => if v.is_empty() {
return Ok(type_report.message(format!("There are no {} types present in context", self.type_name))
.status(Status::SKIP).get_status())
} else { v }
Err(_) => vec![context]
};
let overall = loop {
let mut num_fail = 0;
let mut num_pass = 0;
for (index, each) in values.iter().enumerate() {
let type_context = format!("{}#{}({})", self.type_name, index, (*each).self_path());
let mut each_type_report = AutoReport::new(
EvaluationType::Type,
var_resolver,
&type_context
);
match each_type_report.status(self.block.evaluate(*each, var_resolver)?).get_status() {
Status::PASS => { num_pass += 1; },
Status::FAIL => { num_fail += 1; },
Status::SKIP => {},
}
}
if num_fail > 0 { break Status::FAIL }
if num_pass > 0 { break Status::PASS }
break Status::SKIP
};
Ok(match overall {
Status::SKIP =>
type_report.status(Status::SKIP).message(
format!("ALL Clauses for all types {} was SKIPPED. This can be an error", self.type_name)).get_status(),
rest => type_report.status(rest).get_status()
})
}