alembic-adapter-netbox 0.2.0

NetBox adapter for Alembic.
Documentation
use alembic_core::Uid;
use alembic_engine::{BackendId, StateStore};
use std::collections::BTreeMap;

#[derive(Debug, Default)]
pub(super) struct StateMappings {
    pub(super) by_type: BTreeMap<String, BTreeMap<u64, Uid>>,
}

impl StateMappings {
    pub(super) fn uid_for(&self, type_name: &str, backend_id: u64) -> Option<Uid> {
        self.by_type
            .get(type_name)
            .and_then(|mapping| mapping.get(&backend_id).copied())
    }
}

pub(super) fn state_mappings(state: &StateStore) -> StateMappings {
    let mut by_type = BTreeMap::new();

    for (type_name, mapping) in state.all_mappings() {
        let mut id_to_uid = BTreeMap::new();
        for (uid, backend_id) in mapping {
            if let BackendId::Int(id) = backend_id {
                id_to_uid.insert(*id, *uid);
            }
        }
        by_type.insert(type_name.as_str().to_string(), id_to_uid);
    }

    StateMappings { by_type }
}

pub(super) fn resolved_from_state(state: &StateStore) -> BTreeMap<Uid, u64> {
    let mut resolved = BTreeMap::new();
    for mapping in state.all_mappings().values() {
        for (uid, backend_id) in mapping {
            if let BackendId::Int(id) = backend_id {
                resolved.insert(*uid, *id);
            }
        }
    }
    resolved
}

#[cfg(test)]
mod tests {
    use super::*;
    use alembic_core::TypeName;
    use tempfile::tempdir;

    #[test]
    fn test_state_mappings() {
        let dir = tempdir().unwrap();
        let path = dir.path().join("state.json");
        let mut store = StateStore::load(path).unwrap();
        let uid = Uid::from_u128(1);
        let type_name = TypeName::new("dcim.site");
        store.set_backend_id(type_name.clone(), uid, BackendId::Int(5));

        let mappings = state_mappings(&store);
        assert_eq!(mappings.uid_for("dcim.site", 5), Some(uid));
        assert_eq!(mappings.uid_for("dcim.site", 0), None);
    }

    #[test]
    fn test_resolved_from_state() {
        let dir = tempdir().unwrap();
        let path = dir.path().join("state.json");
        let mut store = StateStore::load(path).unwrap();
        let uid = Uid::from_u128(1);
        store.set_backend_id(TypeName::new("t"), uid, BackendId::Int(5));

        let resolved = resolved_from_state(&store);
        assert_eq!(resolved.get(&uid).copied().unwrap(), 5);
    }
}