Some checks failed
Run Check Script / check (pull_request) Failing after 19s
Move vendor-neutral IaC enums to harmony_types::firewall. Add From impls in opnsense-api::wire converting harmony_types to generated OPNsense types. Add typed methods in opnsense-config that accept harmony_types enums and handle wire conversion internally. Score layer no longer builds serde_json::json!() bodies — it passes harmony_types enums directly to opnsense-config typed methods: ensure_filter_rule(&FirewallAction, &Direction, &IpProtocol, ...) ensure_snat_rule_from(&IpProtocol, &NetworkProtocol, ...) ensure_dnat_rule(&IpProtocol, &NetworkProtocol, ...) ensure_vip_from(&VipMode, ...) ensure_lagg(..., &LaggProtocol, ...) Type flow: harmony_types → Score → opnsense-config → From<> → generated → wire No strings cross layer boundaries for typed fields.
195 lines
6.7 KiB
Rust
195 lines
6.7 KiB
Rust
//! Conversions from vendor-neutral `harmony_types` enums to OPNsense generated API types.
|
|
//!
|
|
//! Each `From` impl maps a harmony IaC type to the corresponding auto-generated
|
|
//! OPNsense enum. The generated types handle wire-format serde serialization.
|
|
|
|
use harmony_types::firewall::{
|
|
Direction, FirewallAction, IpProtocol, LaggProtocol, NetworkProtocol, VipMode,
|
|
};
|
|
|
|
use crate::generated::firewall_filter::{
|
|
FirewallFilterRulesRuleAction, FirewallFilterRulesRuleDirection,
|
|
FirewallFilterRulesRuleIpprotocol, FirewallFilterSnatrulesRuleIpprotocol,
|
|
};
|
|
use crate::generated::lagg::LaggProto;
|
|
use crate::generated::vip::VirtualipVipMode;
|
|
|
|
// ── FirewallAction ──────────────────────────────────────────────────
|
|
|
|
impl From<&FirewallAction> for FirewallFilterRulesRuleAction {
|
|
fn from(value: &FirewallAction) -> Self {
|
|
match value {
|
|
FirewallAction::Pass => Self::Pass,
|
|
FirewallAction::Block => Self::Block,
|
|
FirewallAction::Reject => Self::Reject,
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── Direction ───────────────────────────────────────────────────────
|
|
|
|
impl From<&Direction> for FirewallFilterRulesRuleDirection {
|
|
fn from(value: &Direction) -> Self {
|
|
match value {
|
|
Direction::In => Self::In,
|
|
Direction::Out => Self::Out,
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── IpProtocol → filter rules ───────────────────────────────────────
|
|
|
|
impl From<&IpProtocol> for FirewallFilterRulesRuleIpprotocol {
|
|
fn from(value: &IpProtocol) -> Self {
|
|
match value {
|
|
IpProtocol::Inet => Self::IPv4,
|
|
IpProtocol::Inet6 => Self::IPv6,
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── IpProtocol → SNAT rules ────────────────────────────────────────
|
|
|
|
impl From<&IpProtocol> for FirewallFilterSnatrulesRuleIpprotocol {
|
|
fn from(value: &IpProtocol) -> Self {
|
|
match value {
|
|
IpProtocol::Inet => Self::IPv4,
|
|
IpProtocol::Inet6 => Self::IPv6,
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── NetworkProtocol ─────────────────────────────────────────────────
|
|
// The OPNsense protocol field is a free-form ProtocolField (String),
|
|
// not a generated enum. This is the only case requiring a string conversion.
|
|
|
|
/// Convert a `NetworkProtocol` to the OPNsense wire string.
|
|
///
|
|
/// This is a function (not a `From` impl) because OPNsense's ProtocolField
|
|
/// is a free-form string, not a generated enum. Orphan rules prevent
|
|
/// `impl From<&NetworkProtocol> for String`.
|
|
pub fn network_protocol_to_opnsense(value: &NetworkProtocol) -> String {
|
|
match value {
|
|
NetworkProtocol::Tcp => "TCP".to_string(),
|
|
NetworkProtocol::Udp => "UDP".to_string(),
|
|
NetworkProtocol::TcpUdp => "TCP/UDP".to_string(),
|
|
NetworkProtocol::Icmp => "ICMP".to_string(),
|
|
NetworkProtocol::Any => "any".to_string(),
|
|
}
|
|
}
|
|
|
|
// ── VipMode ─────────────────────────────────────────────────────────
|
|
|
|
impl From<&VipMode> for VirtualipVipMode {
|
|
fn from(value: &VipMode) -> Self {
|
|
match value {
|
|
VipMode::IpAlias => Self::IpAlias,
|
|
VipMode::Carp => Self::Carp,
|
|
VipMode::ProxyArp => Self::ProxyArp,
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── LaggProtocol ────────────────────────────────────────────────────
|
|
|
|
impl From<&LaggProtocol> for LaggProto {
|
|
fn from(value: &LaggProtocol) -> Self {
|
|
match value {
|
|
LaggProtocol::Lacp => Self::Lacp,
|
|
LaggProtocol::Failover => Self::Failover,
|
|
LaggProtocol::LoadBalance => Self::Loadbalance,
|
|
LaggProtocol::RoundRobin => Self::Roundrobin,
|
|
LaggProtocol::None => Self::None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn firewall_action_to_generated() {
|
|
assert_eq!(
|
|
FirewallFilterRulesRuleAction::from(&FirewallAction::Pass),
|
|
FirewallFilterRulesRuleAction::Pass
|
|
);
|
|
assert_eq!(
|
|
FirewallFilterRulesRuleAction::from(&FirewallAction::Block),
|
|
FirewallFilterRulesRuleAction::Block
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn direction_to_generated() {
|
|
assert_eq!(
|
|
FirewallFilterRulesRuleDirection::from(&Direction::In),
|
|
FirewallFilterRulesRuleDirection::In
|
|
);
|
|
assert_eq!(
|
|
FirewallFilterRulesRuleDirection::from(&Direction::Out),
|
|
FirewallFilterRulesRuleDirection::Out
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ip_protocol_to_generated() {
|
|
assert_eq!(
|
|
FirewallFilterRulesRuleIpprotocol::from(&IpProtocol::Inet),
|
|
FirewallFilterRulesRuleIpprotocol::IPv4
|
|
);
|
|
assert_eq!(
|
|
FirewallFilterRulesRuleIpprotocol::from(&IpProtocol::Inet6),
|
|
FirewallFilterRulesRuleIpprotocol::IPv6
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ip_protocol_to_generated_snat() {
|
|
assert_eq!(
|
|
FirewallFilterSnatrulesRuleIpprotocol::from(&IpProtocol::Inet),
|
|
FirewallFilterSnatrulesRuleIpprotocol::IPv4
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn network_protocol_to_wire_string() {
|
|
assert_eq!(network_protocol_to_opnsense(&NetworkProtocol::Tcp), "TCP");
|
|
assert_eq!(network_protocol_to_opnsense(&NetworkProtocol::Any), "any");
|
|
assert_eq!(
|
|
network_protocol_to_opnsense(&NetworkProtocol::TcpUdp),
|
|
"TCP/UDP"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn vip_mode_to_generated() {
|
|
assert_eq!(
|
|
VirtualipVipMode::from(&VipMode::IpAlias),
|
|
VirtualipVipMode::IpAlias
|
|
);
|
|
assert_eq!(
|
|
VirtualipVipMode::from(&VipMode::Carp),
|
|
VirtualipVipMode::Carp
|
|
);
|
|
assert_eq!(
|
|
VirtualipVipMode::from(&VipMode::ProxyArp),
|
|
VirtualipVipMode::ProxyArp
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn lagg_protocol_to_generated() {
|
|
assert_eq!(LaggProto::from(&LaggProtocol::Lacp), LaggProto::Lacp);
|
|
assert_eq!(
|
|
LaggProto::from(&LaggProtocol::Failover),
|
|
LaggProto::Failover
|
|
);
|
|
assert_eq!(
|
|
LaggProto::from(&LaggProtocol::LoadBalance),
|
|
LaggProto::Loadbalance
|
|
);
|
|
assert_eq!(LaggProto::from(&LaggProtocol::None), LaggProto::None);
|
|
}
|
|
}
|