Compare commits
4 commits
5755f08798
...
2c55f5eb54
Author | SHA1 | Date | |
---|---|---|---|
2c55f5eb54 | |||
816480d091 | |||
dcce9113d1 | |||
0c96891a46 |
4 changed files with 135 additions and 15 deletions
98
Cargo.lock
generated
98
Cargo.lock
generated
|
@ -236,6 +236,55 @@ dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-waker"
|
name = "atomic-waker"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
@ -349,6 +398,12 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "convert_case"
|
name = "convert_case"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -451,6 +506,29 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_filter"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"env_filter",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -686,6 +764,12 @@ version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
|
@ -768,6 +852,12 @@ version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -970,7 +1060,9 @@ name = "opentsdb-auth-proxy"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"env_logger",
|
||||||
"glob-match",
|
"glob-match",
|
||||||
|
"log",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -1648,6 +1740,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
|
|
@ -5,7 +5,9 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4.6.0"
|
actix-web = "4.6.0"
|
||||||
|
env_logger = "0.11.3"
|
||||||
glob-match = "0.2.1"
|
glob-match = "0.2.1"
|
||||||
|
log = "0.4.21"
|
||||||
reqwest = "0.12.4"
|
reqwest = "0.12.4"
|
||||||
serde = { version = "1.0.202", features = ["serde_derive"] }
|
serde = { version = "1.0.202", features = ["serde_derive"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
|
|
|
@ -16,6 +16,6 @@ clients:
|
||||||
|
|
||||||
config:
|
config:
|
||||||
opentsdb:
|
opentsdb:
|
||||||
url: http://opentsdb/api
|
url: http://opentsdb/api/
|
||||||
server:
|
server:
|
||||||
port: 8080
|
port: 8080
|
||||||
|
|
48
src/main.rs
48
src/main.rs
|
@ -1,6 +1,7 @@
|
||||||
use actix_web::http::StatusCode;
|
use actix_web::http::StatusCode;
|
||||||
use actix_web::middleware::Logger;
|
use actix_web::middleware::Logger;
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
|
use actix_web::{error, web, App, HttpResponse, HttpServer, Responder};
|
||||||
|
use log::{debug, error, info, log_enabled, Level};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -19,11 +20,19 @@ struct QSParams {
|
||||||
token: String,
|
token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum OtsdbValue {
|
||||||
|
String(String),
|
||||||
|
Integer(i64),
|
||||||
|
Float(f64),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct OtsdbData {
|
struct OtsdbData {
|
||||||
metric: String,
|
metric: String,
|
||||||
value: String,
|
value: OtsdbValue,
|
||||||
timestamp: f64,
|
timestamp: i64,
|
||||||
tags: HashMap<String, String>,
|
tags: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,28 +44,33 @@ async fn put_post(
|
||||||
qs: web::Query<QSParams>,
|
qs: web::Query<QSParams>,
|
||||||
body: web::Json<OtsdbData>,
|
body: web::Json<OtsdbData>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
println!("Body: {:?}", body);
|
|
||||||
let authenticated_client = config::try_authenticate_client(&shared.cfg.clients, &qs.token);
|
let authenticated_client = config::try_authenticate_client(&shared.cfg.clients, &qs.token);
|
||||||
|
|
||||||
if authenticated_client.is_none() {
|
if authenticated_client.is_none() {
|
||||||
return HttpResponse::Unauthorized().body("Unauthorized. Please specify a valid token.");
|
let emsg = format!(
|
||||||
|
"Unauthorized. Unknown token: {}. Please specify a valid tokne.",
|
||||||
|
qs.token
|
||||||
|
);
|
||||||
|
error!("{}", emsg);
|
||||||
|
return HttpResponse::Unauthorized().body(emsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = authenticated_client.unwrap();
|
let client = authenticated_client.unwrap();
|
||||||
|
|
||||||
if !client.can_write(&body.metric) {
|
if !client.can_write(&body.metric) {
|
||||||
return HttpResponse::Forbidden().body(format!(
|
let emsg = format!(
|
||||||
"Not allowed to write metric `{}`. Allowed metrics: {}",
|
"Not allowed to write metric `{}`. Allowed metrics: {}",
|
||||||
body.metric,
|
body.metric,
|
||||||
client.metrics.join(", ")
|
client.metrics.join(", ")
|
||||||
));
|
);
|
||||||
|
error!("{}", emsg);
|
||||||
|
return HttpResponse::Forbidden().body(format!("{}", emsg));
|
||||||
}
|
}
|
||||||
println!("Client: {:?}", client);
|
|
||||||
|
|
||||||
let post_url = format!("{}put", shared.cfg.config.opentsdb.url);
|
let post_url = format!("{}put", shared.cfg.config.opentsdb.url);
|
||||||
let otsdb_body = serde_json::to_string(&body).unwrap();
|
let otsdb_body = serde_json::to_string(&body).unwrap();
|
||||||
|
|
||||||
println!("POST URL: {}", post_url);
|
debug!("POST {} with body: {}", post_url, otsdb_body);
|
||||||
|
|
||||||
let response = shared
|
let response = shared
|
||||||
.web_client
|
.web_client
|
||||||
|
@ -70,11 +84,16 @@ async fn put_post(
|
||||||
let status = resp.status();
|
let status = resp.status();
|
||||||
|
|
||||||
let body = resp.text().await.unwrap_or_else(|_| "".to_string());
|
let body = resp.text().await.unwrap_or_else(|_| "".to_string());
|
||||||
|
debug!("OpenTSDB response {}: {}", status, body);
|
||||||
let sstatus =
|
let sstatus =
|
||||||
StatusCode::from_u16(status.as_u16()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
|
StatusCode::from_u16(status.as_u16()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
|
||||||
HttpResponse::Ok().status(sstatus).body(body)
|
HttpResponse::Ok().status(sstatus).body(body)
|
||||||
}
|
}
|
||||||
Err(err) => HttpResponse::InternalServerError().body(format!("Error: {}", err)),
|
Err(err) => {
|
||||||
|
error!("OpenTSDB error: {}", err);
|
||||||
|
HttpResponse::InternalServerError().body(format!("Proxy error: {}", err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +102,9 @@ async fn main() -> std::io::Result<()> {
|
||||||
let cfg_file = env::var("CONFIG_FILE").unwrap_or(CONFIG_FILE.to_string());
|
let cfg_file = env::var("CONFIG_FILE").unwrap_or(CONFIG_FILE.to_string());
|
||||||
let cfg = config::load_config_file(&cfg_file);
|
let cfg = config::load_config_file(&cfg_file);
|
||||||
|
|
||||||
println!("Config: {:?}", cfg);
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||||
|
|
||||||
|
println!("Loaded config: {:#?}", cfg);
|
||||||
let server_port = cfg.config.server.port.clone();
|
let server_port = cfg.config.server.port.clone();
|
||||||
|
|
||||||
let web_client = Client::new();
|
let web_client = Client::new();
|
||||||
|
@ -96,11 +117,10 @@ async fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
.app_data(client_data.clone()) //.client_data.clone())
|
.app_data(client_data.clone())
|
||||||
.app_data(web::JsonConfig::default().content_type_required(false))
|
.app_data(web::JsonConfig::default().content_type_required(false))
|
||||||
.wrap(Logger::default())
|
.wrap(Logger::new("%r %s")) // k8s already logs timestamp
|
||||||
.service(put_post)
|
.service(put_post)
|
||||||
//.route("/put", web::post().to(put_post))
|
|
||||||
})
|
})
|
||||||
.bind(format!("[::]:{}", server_port))?
|
.bind(format!("[::]:{}", server_port))?
|
||||||
.run()
|
.run()
|
||||||
|
|
Loading…
Reference in a new issue