Structured code into files and added tests for hostname
This commit is contained in:
parent
f16a504bd9
commit
e33b503159
|
@ -2,6 +2,15 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -25,11 +34,19 @@ version = "0.2.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimon"
|
name = "minimon"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ping",
|
"ping",
|
||||||
|
"regex",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -97,6 +114,35 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.10"
|
version = "0.4.10"
|
||||||
|
|
|
@ -5,3 +5,5 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ping = "0.5.2"
|
ping = "0.5.2"
|
||||||
|
regex = "1.10.5"
|
||||||
|
thiserror = "1.0.61"
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
use ::thiserror::Error;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
const VALID_IP_ADDRESS_PATTERN: &str = r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
|
||||||
|
const VALID_HOSTNAME_PATTERN: &str = r"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$";
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Error)]
|
||||||
|
#[error("The hostname \"{0}\" is invalid")]
|
||||||
|
pub struct InvalidHostnameError(String);
|
||||||
|
|
||||||
|
pub struct Hostname {
|
||||||
|
hostname: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hostname {
|
||||||
|
pub fn new(hostname: &str) -> Result<Hostname, InvalidHostnameError> {
|
||||||
|
if Self::is_valid_ip(&hostname) || Self::is_valid_hostname(&hostname) {
|
||||||
|
Ok(Hostname {
|
||||||
|
hostname: hostname.to_string(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(InvalidHostnameError(hostname.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_ip(ip: &str) -> bool {
|
||||||
|
let re = Regex::new(VALID_IP_ADDRESS_PATTERN).unwrap();
|
||||||
|
re.is_match(ip)
|
||||||
|
}
|
||||||
|
fn is_valid_hostname(hostname: &str) -> bool {
|
||||||
|
let re = Regex::new(VALID_HOSTNAME_PATTERN).unwrap();
|
||||||
|
re.is_match(hostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn valid_ip_adresses() {
|
||||||
|
assert!(Hostname::new("192.168.0.1").is_ok());
|
||||||
|
assert!(Hostname::new("255.127.63.31").is_ok());
|
||||||
|
assert!(Hostname::new("1.0.0.1").is_ok());
|
||||||
|
assert!(Hostname::new("10.1.10.47").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_ip_adresses() {
|
||||||
|
assert!(Hostname::new("::1").is_err()); // We don't support IPv6 yet
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn valid_hostnames() {
|
||||||
|
assert!(Hostname::new("mononobe.fai.st").is_ok());
|
||||||
|
assert!(Hostname::new("twink-pad").is_ok());
|
||||||
|
assert!(Hostname::new("is-42-the-response").is_ok());
|
||||||
|
assert!(Hostname::new("GoB.NaSa-42.eu").is_ok());
|
||||||
|
assert!(Hostname::new("256.127.63.31").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_hostnames() {
|
||||||
|
assert!(Hostname::new("no..double.dots").is_err());
|
||||||
|
assert!(Hostname::new("#illegal-character").is_err()); // We don't support IPv6 yet
|
||||||
|
assert!(Hostname::new("").is_err());
|
||||||
|
assert!(Hostname::new("not-end-with-hyphen-").is_err());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,38 +1,30 @@
|
||||||
use std::{collections::HashMap, net::IpAddr};
|
use crate::hostname::Hostname;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
name: String,
|
name: String,
|
||||||
address: IpAddr,
|
hostname: Hostname,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Status {
|
pub enum Status {
|
||||||
Unreachable,
|
Unreachable,
|
||||||
Forbidden,
|
Forbidden,
|
||||||
Success(HashMap<String, String>),
|
Success(HashMap<String, String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
fn new(name: &str, address: IpAddr) -> Machine {
|
pub fn new(name: &str, hostname: Hostname) -> Machine {
|
||||||
Machine {
|
Machine {
|
||||||
name: String::from(name),
|
name: String::from(name),
|
||||||
address,
|
hostname,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Monitor {
|
pub trait Monitor {
|
||||||
fn monitor(machine: &Machine) -> Status;
|
fn monitor(machine: &Machine) -> Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct PingMonitor {}
|
|
||||||
|
|
||||||
impl Monitor for PingMonitor {
|
|
||||||
fn monitor(machine: &Machine) -> Status {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SshMonitor {}
|
struct SshMonitor {}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
mod hostname;
|
||||||
mod machine;
|
mod machine;
|
||||||
|
mod ping_monitor;
|
||||||
use machine::Machine;
|
use machine::Machine;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::machine::{Machine, Monitor, Status};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct PingMonitor {}
|
||||||
|
|
||||||
|
impl Monitor for PingMonitor {
|
||||||
|
fn monitor(machine: &Machine) -> Status {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
#[test]
|
||||||
|
fn monitor_works() {
|
||||||
|
assert!(true)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue