web3-proxy/web3_proxy/tests/common/influx.rs
2023-07-21 23:34:54 -07:00

185 lines
5.5 KiB
Rust

use ethers::prelude::rand::{self, distributions::Alphanumeric, Rng};
use influxdb2::Client;
use std::process::Command as SyncCommand;
use std::time::Duration;
use tokio::{
net::TcpStream,
process::Command as AsyncCommand,
time::{sleep, Instant},
};
use tracing::{info, trace};
/// on drop, the mysql docker container will be shut down
#[derive(Debug)]
pub struct TestInflux {
pub host: String,
pub org: String,
pub token: String,
pub bucket: String,
pub container_name: String,
pub client: Client,
}
impl TestInflux {
#[allow(unused)]
pub async fn spawn() -> Self {
let random: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(8)
.map(char::from)
.collect();
let container_name = format!("web3-proxy-test-influx-{}", random);
info!(%container_name);
// docker run -d -p 8086:8086 \
// --name influxdb2 \
// -v $PWD/data:/var/lib/influxdb2 \
// -v $PWD/config:/etc/influxdb2 \
// -e DOCKER_INFLUXDB_INIT_MODE=setup \
// -e DOCKER_INFLUXDB_INIT_USERNAME=root \
// -e DOCKER_INFLUXDB_INIT_PASSWORD=secret-password \
// -e DOCKER_INFLUXDB_INIT_ORG=my-init-org \
// -e DOCKER_INFLUXDB_INIT_BUCKET=my-init-bucket \
// -e DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=secret-token \
let username = "dev_web3_proxy";
let password = "dev_web3_proxy";
let org = "dev_org";
let init_bucket = "dev_web3_proxy";
let admin_token = "dev_web3_proxy_auth_token";
let cmd = AsyncCommand::new("docker")
.args([
"run",
"--name",
&container_name,
"--rm",
"-d",
"-e",
"DOCKER_INFLUXDB_INIT_MODE=setup",
"-e",
&format!("DOCKER_INFLUXDB_INIT_USERNAME={}", username),
"-e",
&format!("DOCKER_INFLUXDB_INIT_PASSWORD={}", password),
"-e",
&format!("DOCKER_INFLUXDB_INIT_ORG={}", org),
"-e",
&format!("DOCKER_INFLUXDB_INIT_BUCKET={}", init_bucket),
"-e",
&format!("DOCKER_INFLUXDB_INIT_ADMIN_TOKEN={}", admin_token),
"-p",
"0:8086",
"influxdb:2.6.1-alpine",
])
.output()
.await
.expect("failed to start influx");
// original port 18086
info!("Creation command is: {:?}", cmd);
// give the db a second to start
// TODO: wait until docker says it is healthy
sleep(Duration::from_secs(1)).await;
let docker_inspect_output = AsyncCommand::new("docker")
.args(["inspect", &container_name])
.output()
.await
.unwrap();
info!(?docker_inspect_output);
let docker_inspect_json = String::from_utf8(docker_inspect_output.stdout).unwrap();
info!(%docker_inspect_json);
let docker_inspect_json: serde_json::Value =
serde_json::from_str(&docker_inspect_json).unwrap();
let influx_ports = docker_inspect_json
.get(0)
.unwrap()
.get("NetworkSettings")
.unwrap()
.get("Ports")
.unwrap()
.get("8086/tcp")
.unwrap()
.get(0)
.unwrap();
trace!(?influx_ports);
let influx_port: u64 = influx_ports
.get("HostPort")
.expect("unable to determine influx port")
.as_str()
.unwrap()
.parse()
.unwrap();
let influx_ip = influx_ports
.get("HostIp")
.and_then(|x| x.as_str())
.expect("unable to determine influx ip");
// let host = "http://localhost:8086";
let influx_host = format!("http://{}:{}", influx_ip, influx_port);
info!(%influx_host);
// Create the client ...
let influxdb_client = influxdb2::Client::new(influx_host.clone(), org, admin_token);
info!("Influx client is: {:?}", influxdb_client);
// create the TestInflux as soon as the url is known
// when this is dropped, the docker container will be stopped
let mut test_influx = Self {
host: influx_host,
org: org.to_string(),
token: admin_token.to_string(),
bucket: init_bucket.to_string(),
container_name: container_name.clone(),
client: influxdb_client,
};
let start = Instant::now();
let max_wait = Duration::from_secs(30);
loop {
if start.elapsed() > max_wait {
panic!("influx took too long to start");
}
if TcpStream::connect(format!("{}:{}", influx_ip, influx_port))
.await
.is_ok()
{
break;
};
// not open wait. sleep and then try again
sleep(Duration::from_secs(1)).await;
}
sleep(Duration::from_secs(1)).await;
// TODO: try to use the influx client
info!(?test_influx, elapsed=%start.elapsed().as_secs_f32(), "influx port is open");
test_influx
}
}
impl Drop for TestInflux {
fn drop(&mut self) {
info!(%self.container_name, "killing influx");
let _ = SyncCommand::new("docker")
.args(["kill", "-s", "9", &self.container_name])
.output();
}
}