Setup custom api client
This commit is contained in:
parent
6e6a589f38
commit
90abd08088
950
Cargo.lock
generated
950
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -6,11 +6,11 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
http = "1.1.0"
|
|
||||||
proxmox-client = { git = "git://git.proxmox.com/git/proxmox.git", branch = "master", features = ["hyper-client"] }
|
|
||||||
tokio = { version = "1.37.0", features = ["rt", "rt-multi-thread", "macros"] }
|
tokio = { version = "1.37.0", features = ["rt", "rt-multi-thread", "macros"] }
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.83"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
config = { version = "0.14.0", features = ["toml"] }
|
config = { version = "0.14.0", features = ["toml"] }
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger = "0.5.0"
|
||||||
serde = { version = "1.0.213", features = ["derive"] }
|
serde = { version = "1.0.213", features = ["derive"] }
|
||||||
|
reqwest = { version = "0.12.8", features = ["json"] }
|
||||||
|
serde_json = "1.0.132"
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
server = "10.97.0.234"
|
server = "https://10.97.0.234:8006/"
|
||||||
token_id = "root@pam!test-dev"
|
user = "root"
|
||||||
|
realm = "pam"
|
||||||
|
token_id = "test-dev"
|
||||||
secret = "e2d8d39f-63ce-48f0-a025-b428d29a26e3"
|
secret = "e2d8d39f-63ce-48f0-a025-b428d29a26e3"
|
35
src/main.rs
35
src/main.rs
@ -1,33 +1,32 @@
|
|||||||
use std::default;
|
use config::{Config, File};
|
||||||
use config::{Config, ConfigBuilder};
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use proxmox_client::{AuthenticationKind, HttpApiClient, TlsOptions, Token};
|
use crate::proxmox::{Client, VersionResponse};
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
mod settings;
|
mod settings;
|
||||||
|
mod proxmox;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), anyhow::Error> {
|
async fn main() -> Result<(), anyhow::Error> {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
let config: Settings = Config::builder()
|
let config: Settings = Config::builder()
|
||||||
.add_source("config.toml")
|
.add_source(File::with_name("config.toml"))
|
||||||
.build()?.try_deserialize()?;
|
.build()?.try_deserialize()?;
|
||||||
|
|
||||||
let client = proxmox_client::Client::with_options(
|
let client = Client::new(config.server.parse()?)
|
||||||
config.server,
|
.with_api_token(
|
||||||
TlsOptions::Insecure,
|
&config.user,
|
||||||
Default::default())?;
|
&config.realm,
|
||||||
|
&config.token_id,
|
||||||
|
&config.secret,
|
||||||
|
);
|
||||||
|
|
||||||
client.set_authentication(AuthenticationKind::Token(Token {
|
let nodes = client.list_nodes().await.expect("Error listing nodes");
|
||||||
userid: config.token_id.clone(),
|
for n in &nodes {
|
||||||
prefix: "PVEAPIToken".to_string(),
|
let vms = client.list_vms(&n.name).await?;
|
||||||
value: config.secret.clone(),
|
for vm in &vms {
|
||||||
perl_compat: false,
|
}
|
||||||
}));
|
}
|
||||||
|
|
||||||
let rsp = client.get("/api2/json/version").await?;
|
|
||||||
let string = String::from_utf8(rsp.body)?;
|
|
||||||
info!("Version: {}", string);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
135
src/proxmox.rs
Normal file
135
src/proxmox.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use anyhow::Error;
|
||||||
|
use log::info;
|
||||||
|
use reqwest::{Body, ClientBuilder, Request, RequestBuilder, Url};
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
|
pub struct ClientToken {
|
||||||
|
username: String,
|
||||||
|
realm: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Client {
|
||||||
|
base: Url,
|
||||||
|
token: ClientToken,
|
||||||
|
client: reqwest::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
pub fn new(base: Url) -> Self {
|
||||||
|
let mut client = ClientBuilder::new()
|
||||||
|
.danger_accept_invalid_certs(true)
|
||||||
|
.build().expect("Failed to build client");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
base,
|
||||||
|
token: ClientToken::default(),
|
||||||
|
client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_api_token(mut self, user: &str, realm: &str, token_id: &str, secret: &str) -> Self {
|
||||||
|
// PVEAPIToken=USER@REALM!TOKENID=UUID
|
||||||
|
self.token = ClientToken {
|
||||||
|
username: user.to_string(),
|
||||||
|
realm: realm.to_string(),
|
||||||
|
password: format!("{}@{}!{}={}", user, realm, token_id, secret),
|
||||||
|
};
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get version info
|
||||||
|
pub async fn version(&self) -> Result<VersionResponse, Error> {
|
||||||
|
let rsp: ResponseBase<VersionResponse> = self.get("/api2/json/version").await?;
|
||||||
|
Ok(rsp.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List nodes
|
||||||
|
pub async fn list_nodes(&self) -> Result<Vec<NodeResponse>, Error> {
|
||||||
|
let rsp: ResponseBase<Vec<NodeResponse>> = self.get("/api2/json/nodes").await?;
|
||||||
|
Ok(rsp.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_vms(&self, node: &str) -> Result<Vec<VmInfo>, Error> {
|
||||||
|
let rsp: ResponseBase<Vec<VmInfo>> = self.get(&format!("/api2/json/nodes/{}/qemu", node)).await?;
|
||||||
|
Ok(rsp.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get<T: DeserializeOwned>(&self, path: &str) -> Result<T, Error> {
|
||||||
|
let rsp = self.client
|
||||||
|
.get(self.base.join(path)?)
|
||||||
|
.header("Authorization", format!("PVEAPIToken={}", self.token.password))
|
||||||
|
.send().await?
|
||||||
|
.error_for_status()?;
|
||||||
|
let text = rsp.text().await?;
|
||||||
|
info!("{}->{}", path, text);
|
||||||
|
Ok(serde_json::from_str(&text)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn post<T: DeserializeOwned, R: Into<Body>>(&self, path: &str, body: R) -> Result<T, Error> {
|
||||||
|
Ok(
|
||||||
|
self.client
|
||||||
|
.post(self.base.join(path)?)
|
||||||
|
.header("Authorization", format!("PVEAPIToken={}", self.token.password))
|
||||||
|
.body(body)
|
||||||
|
.send().await?
|
||||||
|
.error_for_status()?
|
||||||
|
.json().await?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ResponseBase<T>
|
||||||
|
{
|
||||||
|
pub data: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct VersionResponse {
|
||||||
|
#[serde(rename = "repoid")]
|
||||||
|
pub repo_id: String,
|
||||||
|
pub version: String,
|
||||||
|
pub release: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum NodeStatus {
|
||||||
|
Unknown,
|
||||||
|
Online,
|
||||||
|
Offline,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct NodeResponse {
|
||||||
|
#[serde(rename = "node")]
|
||||||
|
pub name: String,
|
||||||
|
pub status: NodeStatus,
|
||||||
|
pub cpu: Option<f32>,
|
||||||
|
pub support: Option<String>,
|
||||||
|
#[serde(rename = "maxcpu")]
|
||||||
|
pub max_cpu: Option<u16>,
|
||||||
|
#[serde(rename = "maxmem")]
|
||||||
|
pub max_mem: Option<u64>,
|
||||||
|
pub mem: Option<u64>,
|
||||||
|
pub uptime: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum VmStatus {
|
||||||
|
Stopped,
|
||||||
|
Running,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct VmInfo {
|
||||||
|
pub status: VmStatus,
|
||||||
|
#[serde(rename = "vmid")]
|
||||||
|
pub vm_id: i32,
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
use http::Uri;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub server: Uri,
|
pub server: String,
|
||||||
|
pub user: String,
|
||||||
|
pub realm: String,
|
||||||
pub token_id: String,
|
pub token_id: String,
|
||||||
pub secret: String,
|
pub secret: String,
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user