greentic-operator 0.4.43

Greentic operator CLI for local dev and demo orchestration.
Documentation
use super::{GmapPath, GmapRule, Policy};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MatchDecision {
    pub policy: Policy,
    pub rank: u8,
}

pub fn eval_policy(rules: &[GmapRule], target: &GmapPath) -> Option<MatchDecision> {
    let mut best: Option<MatchDecision> = None;
    let mut best_index = 0usize;
    for (idx, rule) in rules.iter().enumerate() {
        if !matches_target(&rule.path, target) {
            continue;
        }
        let rank = specificity_rank(&rule.path);
        let candidate = MatchDecision {
            policy: rule.policy.clone(),
            rank,
        };
        match best {
            None => {
                best = Some(candidate);
                best_index = idx;
            }
            Some(ref current) => {
                if rank > current.rank || (rank == current.rank && idx > best_index) {
                    best = Some(candidate);
                    best_index = idx;
                }
            }
        }
    }
    best
}

pub fn eval_with_overlay(
    tenant_rules: &[GmapRule],
    team_rules: &[GmapRule],
    target: &GmapPath,
) -> Option<MatchDecision> {
    eval_policy(team_rules, target).or_else(|| eval_policy(tenant_rules, target))
}

fn matches_target(rule: &GmapPath, target: &GmapPath) -> bool {
    match (&rule.pack, &rule.flow, &rule.node) {
        (None, None, None) => true,
        (Some(pack), None, None) => target.pack.as_deref() == Some(pack.as_str()),
        (Some(pack), Some(flow), None) => {
            if flow == "_" {
                target.pack.as_deref() == Some(pack.as_str())
            } else {
                target.pack.as_deref() == Some(pack.as_str())
                    && target.flow.as_deref() == Some(flow.as_str())
            }
        }
        (Some(pack), Some(flow), Some(node)) => {
            target.pack.as_deref() == Some(pack.as_str())
                && target.flow.as_deref() == Some(flow.as_str())
                && target.node.as_deref() == Some(node.as_str())
        }
        _ => false,
    }
}

fn specificity_rank(path: &GmapPath) -> u8 {
    match (&path.pack, &path.flow, &path.node) {
        (None, None, None) => 0,
        (Some(_), None, None) => 3,
        (Some(_), Some(flow), None) if flow == "_" => 2,
        (Some(_), Some(_), None) => 4,
        (Some(_), Some(_), Some(_)) => 5,
        _ => 0,
    }
}