last_order 0.1.5

A Rust library for managing network devices.
Documentation
use std::net::ToSocketAddrs;

use regex::Regex;

use crate::error::Error;
use crate::generic::config::{ConfigSession, ConfigurationMode};
use crate::generic::connection::{Connection, SSHConnection};
use crate::generic::device::NetworkDevice;

pub type CiscoSSH = CiscoDevice<SSHConnection>;

/// Cisco network device implementation.
pub struct CiscoDevice<C: Connection> {
    connection: C,
    prompt: Regex,
}

impl<C: Connection<ConnectionHandler = C>> NetworkDevice for CiscoDevice<C> {
    fn as_any(&mut self) -> &mut dyn std::any::Any
    where
        Self: 'static,
    {
        self
    }

    fn connect<A: ToSocketAddrs>(
        addr: A,
        username: Option<&str>,
        password: Option<&str>,
    ) -> Result<Self, Error> {
        let mut device = Self {
            connection: C::connect(addr, username, password)?,
            prompt: Regex::new(r"[a-zA-Z0-9_-]+(\(config\))?#$").expect("Invalid prompt regex"),
        };

        device.connection.read(&device.prompt)?;
        device.execute("terminal length 0")?;

        Ok(device)
    }

    fn execute(&mut self, command: &str) -> Result<String, Error> {
        self.connection.execute(command, &self.prompt)
    }

    fn enter_config(&mut self) -> Result<Box<dyn ConfigSession + '_>, Error> {
        self.execute("configure terminal")?;

        Ok(Box::new(ConfigurationMode::new(self)))
    }

    fn exit(&mut self) -> Result<(), Error> {
        self.execute("end")?;

        Ok(())
    }

    fn version(&mut self) -> Result<String, Error> {
        self.execute("show version")
    }

    fn logbuffer(&mut self) -> Result<String, Error> {
        self.execute("show logging")
    }

    fn ping(&mut self, ip: &str) -> Result<String, Error> {
        let command = format!("ping {}", ip);

        self.execute(&command)
    }
}

#[cfg(test)]
mod tests {
    #[allow(unused_imports)]
    use crate::{create_network_device, Vendor};

    #[ignore = "no test device"]
    #[test]
    fn test_cisco() -> anyhow::Result<()> {
        // Placeholder test; update with actual device details
        Ok(())
    }
}