wg show <interface> if specified in the command line (#17)
Using `interface` instead of `all` if specified
This commit is contained in:
parent
42ae2f5927
commit
e04a3f833b
4 changed files with 107 additions and 36 deletions
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "prometheus_wireguard_exporter"
|
||||
version = "3.1.1"
|
||||
version = "3.2.0"
|
||||
authors = ["Francesco Cogno <francesco.cogno@outlook.com>"]
|
||||
description = "Prometheus WireGuard Exporter"
|
||||
edition = "2018"
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
|
||||
[![Crate](https://img.shields.io/crates/v/prometheus_wireguard_exporter.svg)](https://crates.io/crates/prometheus_wireguard_exporter) [![cratedown](https://img.shields.io/crates/d/prometheus_wireguard_exporter.svg)](https://crates.io/crates/prometheus_wireguard_exporter) [![cratelastdown](https://img.shields.io/crates/dv/prometheus_wireguard_exporter.svg)](https://crates.io/crates/prometheus_wireguard_exporter)
|
||||
|
||||
[![release](https://img.shields.io/github/release/MindFlavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.1.1)
|
||||
[![tag](https://img.shields.io/github/tag/mindflavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.1.1)
|
||||
[![release](https://img.shields.io/github/release/MindFlavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.2.0)
|
||||
[![tag](https://img.shields.io/github/tag/mindflavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.2.0)
|
||||
|
||||
[![Build Status](https://travis-ci.org/MindFlavor/prometheus_wireguard_exporter.svg?branch=master)](https://travis-ci.org/MindFlavor/prometheus_wireguard_exporter)
|
||||
[![commitssince](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.1.1.svg)](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.1.1.svg)
|
||||
[![commitssince](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.2.0.svg)](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.2.0.svg)
|
||||
|
||||
## Intro
|
||||
|
||||
A Prometheus exporter for [WireGuard](https://www.wireguard.com), written in Rust. This tool exports the `wg show all dump` results in a format that [Prometheus](https://prometheus.io/) can understand. The exporter is very light on your server resources, both in terms of memory and CPU usage.
|
||||
A Prometheus exporter for [WireGuard](https://www.wireguard.com), written in Rust. This tool exports the `wg show all dump` (or `wg show <interface> dump` if you specify a config file) results in a format that [Prometheus](https://prometheus.io/) can understand. The exporter is very light on your server resources, both in terms of memory and CPU usage.
|
||||
|
||||
Starting from release [2.0.2](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/2.0.2) this exporter supports IPv6 addressess too (thanks to [Maximilian Bosch](https://github.com/Ma27)'s PR [#5](https://github.com/MindFlavor/prometheus_wireguard_exporter/pull/5)).
|
||||
From release [3.0.0](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.0.0) the exporter allows two label modes: one is to dump every allowed ip in a single label (called `allowed_ips`) along with their subnets. The second one is to create a pair of labels for each allowed ip/subnet pair (called `allowed_ip_0`/`allowed_subnet_0`, `allowed_ip_1`/`allowed_subnet_1` and so on for every allowed ip). The default if the single label mode but you can enable the second mode by specifying the `-s` switch at startup. Thank you [Toon Schoenmakers](https://github.com/schoentoon) for this solution (see [https://github.com/MindFlavor/prometheus_wireguard_exporter/issues/8](https://github.com/MindFlavor/prometheus_wireguard_exporter/issues/8)).
|
||||
|
|
91
src/main.rs
91
src/main.rs
|
@ -5,7 +5,7 @@ use clap;
|
|||
use clap::{crate_authors, crate_name, crate_version, Arg};
|
||||
use futures::future::{done, ok, Either, Future};
|
||||
use hyper::{Body, Request, Response};
|
||||
use log::{info, trace};
|
||||
use log::{debug, info, trace};
|
||||
use std::env;
|
||||
mod options;
|
||||
use options::Options;
|
||||
|
@ -25,14 +25,13 @@ use std::sync::Arc;
|
|||
|
||||
fn wg_with_text(
|
||||
wg_config_str: &str,
|
||||
wg_output: ::std::process::Output,
|
||||
wg_output_str: &str,
|
||||
options: Arc<Options>,
|
||||
) -> Result<Response<Body>, ExporterError> {
|
||||
let pehm = peer_entry_hashmap_try_from(wg_config_str)?;
|
||||
trace!("pehm == {:?}", pehm);
|
||||
|
||||
let wg_output_string = String::from_utf8(wg_output.stdout)?;
|
||||
let wg = WireGuard::try_from(&wg_output_string as &str)?;
|
||||
let wg = WireGuard::try_from(wg_output_str)?;
|
||||
Ok(Response::new(Body::from(wg.render_with_names(
|
||||
Some(&pehm),
|
||||
options.separate_allowed_ips,
|
||||
|
@ -45,45 +44,75 @@ fn perform_request(
|
|||
options: &Arc<Options>,
|
||||
) -> impl Future<Item = Response<Body>, Error = failure::Error> {
|
||||
trace!("perform_request");
|
||||
|
||||
// this is needed to satisfy the borrow checker
|
||||
let options = options.clone();
|
||||
debug!("options == {:?}", options);
|
||||
|
||||
//let interface = options.get_interface();
|
||||
|
||||
let interface_str = match options.get_interface() {
|
||||
Some(interface_str) => interface_str,
|
||||
None => "all",
|
||||
}
|
||||
.to_owned();
|
||||
|
||||
debug!("using inteface_str {}", interface_str);
|
||||
|
||||
done(
|
||||
Command::new("wg")
|
||||
.arg("show")
|
||||
.arg("all")
|
||||
.arg(&interface_str)
|
||||
.arg("dump")
|
||||
.output(),
|
||||
)
|
||||
.from_err()
|
||||
.and_then(move |output| {
|
||||
if let Some(extract_names_config_file) = &options.extract_names_config_file {
|
||||
Either::A(
|
||||
done(::std::fs::read_to_string(extract_names_config_file))
|
||||
.from_err()
|
||||
.and_then(|wg_config_string| {
|
||||
wg_with_text(&wg_config_string as &str, output, options)
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
Either::B(done(String::from_utf8(output.stdout)).from_err().and_then(
|
||||
move |output_str| {
|
||||
trace!("{}", output_str);
|
||||
done(WireGuard::try_from(&output_str as &str))
|
||||
.from_err()
|
||||
.and_then(move |wg| {
|
||||
ok(Response::new(Body::from(wg.render_with_names(
|
||||
None,
|
||||
options.separate_allowed_ips,
|
||||
options.export_remote_ip_and_port,
|
||||
))))
|
||||
})
|
||||
},
|
||||
))
|
||||
}
|
||||
done(String::from_utf8(output.stdout))
|
||||
.from_err()
|
||||
.and_then(move |output_str| {
|
||||
trace!("wg show output == {}", output_str);
|
||||
|
||||
// the output of wg show is different if we use all or we specify an interface.
|
||||
// In the first case the first column will be the interface name. In the second case
|
||||
// the interface name will be omitted. We need to compensate for the skew somehow (one
|
||||
// column less in the second case). We solve this prepending the interface name in every
|
||||
// line so the output of the second case will be equal to the first case.
|
||||
let output_str = if interface_str != "all" {
|
||||
debug!("injecting {} to the wg show output", interface_str);
|
||||
let mut result = String::new();
|
||||
for s in output_str.lines() {
|
||||
result.push_str(&format!("{}\t{}\n", interface_str, s));
|
||||
}
|
||||
result
|
||||
} else {
|
||||
output_str
|
||||
};
|
||||
|
||||
if let Some(extract_names_config_file) = &options.extract_names_config_file {
|
||||
Either::A(
|
||||
done(::std::fs::read_to_string(extract_names_config_file))
|
||||
.from_err()
|
||||
.and_then(move |wg_config_string| {
|
||||
wg_with_text(&wg_config_string as &str, &output_str, options)
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
Either::B({
|
||||
trace!("{}", output_str);
|
||||
done(WireGuard::try_from(&output_str as &str))
|
||||
.from_err()
|
||||
.and_then(move |wg| {
|
||||
ok(Response::new(Body::from(wg.render_with_names(
|
||||
None,
|
||||
options.separate_allowed_ips,
|
||||
options.export_remote_ip_and_port,
|
||||
))))
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
.from_err()
|
||||
})
|
||||
.from_err()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -24,4 +24,46 @@ impl Options {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_interface(&self) -> Option<&str> {
|
||||
if let Some(config_file) = &self.extract_names_config_file {
|
||||
let path = std::path::Path::new(config_file);
|
||||
if let Some(file_stem) = path.file_stem() {
|
||||
file_stem.to_str()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_interface_some() {
|
||||
let options = Options {
|
||||
verbose: true,
|
||||
separate_allowed_ips: false,
|
||||
extract_names_config_file: Some("/etc/wireguard/wg0.conf".to_owned()),
|
||||
export_remote_ip_and_port: true,
|
||||
};
|
||||
|
||||
assert_eq!(options.get_interface(), Some("wg0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interface_none() {
|
||||
let options = Options {
|
||||
verbose: true,
|
||||
separate_allowed_ips: false,
|
||||
extract_names_config_file: None,
|
||||
export_remote_ip_and_port: true,
|
||||
};
|
||||
|
||||
assert_eq!(options.get_interface(), None);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue