Files
tsunagi/src/dataplane/wireguard/provision/unsupported.rs
T

81 lines
2.5 KiB
Rust
Raw Normal View History

//! The provisioner for platforms that do not have one yet.
//!
//! macOS and Windows both need real work here — `utun` plus the
//! `SystemConfiguration` framework on one, the IP Helper API and a Wintun
//! adapter on the other — and neither is written. Rather than let the agent
//! come up and fail obscurely at the first packet, this refuses at the point
//! of provisioning and says what to do instead.
use crate::BoxFuture;
use crate::dataplane::PluginError;
use super::{InterfacePlan, InterfaceProvisioner, Provisioned};
/// Refuses to provision, with an explanation.
#[derive(Debug, Clone)]
pub struct UnsupportedProvisioner {
platform: &'static str,
}
impl Default for UnsupportedProvisioner {
fn default() -> Self {
Self::new()
}
}
impl UnsupportedProvisioner {
/// A provisioner naming the platform it is standing in for.
pub fn new() -> Self {
Self {
platform: std::env::consts::OS,
}
}
fn refusal(&self) -> PluginError {
PluginError::Unavailable(format!(
"managing the overlay interface is not implemented on {} yet. \
Prepare the interface by hand — `tsunagi tun-setup` prints what to run — \
and the agent will attach to it.",
self.platform
))
}
}
impl InterfaceProvisioner for UnsupportedProvisioner {
fn name(&self) -> &str {
"unsupported"
}
fn reconcile<'a>(
&'a self,
_plan: &'a InterfacePlan,
) -> BoxFuture<'a, Result<Provisioned, PluginError>> {
Box::pin(async move { Err(self.refusal()) })
}
fn remove<'a>(&'a self, _name: &'a str) -> BoxFuture<'a, Result<(), PluginError>> {
// Nothing was ever created, so there is nothing to clean up and no
// reason to fail a shutdown path.
Box::pin(async move { Ok(()) })
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use super::*;
#[tokio::test]
async fn it_refuses_with_a_usable_pointer_and_still_cleans_up_quietly() {
let provisioner = UnsupportedProvisioner::new();
let plan = InterfacePlan::new("tsuntest", 1280, Vec::new());
let err = provisioner.reconcile(&plan).await.unwrap_err();
let message = err.to_string();
assert!(message.contains("tun-setup"), "{message}");
assert!(message.contains(std::env::consts::OS), "{message}");
provisioner.remove("tsuntest").await.unwrap();
}
}