1#![warn(missing_docs)]
6#![allow(clippy::style)]
7
8use std::{io, env};
9use std::sync::RwLock;
10
11pub mod data;
12mod config;
13pub use config::*;
14
15pub use ureq::http::Uri;
16
17const MAX_BODY_SIZE: u64 = 10 * 1024 * 1024;
18
19pub fn pod_name() -> Option<String> {
25 env::var("POD_NAME").or_else(|_| env::var("HOSTNAME")).ok()
26}
27
28struct State {
29 auth_token: RwLock<ClusterToken>,
30 namespace: String,
31 uri: Uri,
32}
33
34#[derive(Clone)]
35pub struct Client {
37 http: ureq::Agent,
38 state: std::sync::Arc<State>
39}
40
41impl Client {
42 pub fn new(http: HttpConfig, KubeConfig { auth_token, uri, certs, namespace }: KubeConfig) -> Self {
44 let state = State {
45 auth_token: RwLock::new(auth_token),
46 uri,
47 namespace
48 };
49
50 let ca = ureq::tls::RootCerts::Specific(std::sync::Arc::new(certs));
51 let tls_config = ureq::tls::TlsConfig::builder().use_sni(false).root_certs(ca).build();
52 let http = ureq::Agent::config_builder().timeout_per_call(Some(http.timeout)).tls_config(tls_config).build();
53 let http = ureq::Agent::new_with_config(http);
54 Self {
55 http,
56 state: std::sync::Arc::new(state)
57 }
58 }
59
60 pub fn get_pod(&self, pod_name: &str) -> Result<data::Pod, ureq::Error> {
62 let auth_token = self.state.auth_token.read().expect("internal error");
63 let bearer = if auth_token.is_expired() {
64 drop(auth_token);
65 let mut auth_token = self.state.auth_token.write().expect("internal error");
66 auth_token.refresh();
67 format!("Bearer {}", auth_token.token())
68 } else {
69 let result = format!("Bearer {}", auth_token.token());
70 drop(auth_token);
71 result
72 };
73
74 let uri = format!("{}/api/v1/namespaces/{}/pods/{pod_name}", self.state.uri, self.state.namespace);
75 let response = self.http.get(&uri).header("Authorization", bearer).call()?;
76 let body = response.into_body().into_with_config().limit(MAX_BODY_SIZE).reader();
77 serde_json::from_reader(body).map_err(|error| {
78 if error.is_io() || error.is_eof() {
79 ureq::Error::Io(io::Error::other(error))
80 } else {
81 ureq::Error::Other(Box::new(error))
82 }
83 })
84 }
85}