Skip to content

Commit 592fdc1

Browse files
committed
added kubelet.rs
1 parent 7b39422 commit 592fdc1

File tree

5 files changed

+79
-0
lines changed

5 files changed

+79
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ educe = { version = "0.6.0", default-features = false, features = ["Clone", "De
2525
either = "1.13.0"
2626
futures = "0.3.30"
2727
futures-util = "0.3.30"
28+
http = "1.3.1"
2829
indexmap = "2.5.0"
2930
indoc = "2.0.6"
3031
insta = { version= "1.40", features = ["glob"] }

crates/stackable-operator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dockerfile-parser.workspace = true
2828
either.workspace = true
2929
educe.workspace = true
3030
futures.workspace = true
31+
http.workspace = true
3132
indexmap.workspace = true
3233
json-patch.workspace = true
3334
k8s-openapi.workspace = true
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use k8s_openapi::api::core::v1::Node;
2+
use kube::{
3+
Api,
4+
api::{ListParams, ResourceExt},
5+
client::Client,
6+
};
7+
use serde::Deserialize;
8+
use http;
9+
use snafu::{Snafu, ResultExt, OptionExt};
10+
11+
#[derive(Debug, Snafu)]
12+
pub enum Error {
13+
14+
#[snafu(display("failed to list nodes"))]
15+
ListNodes {
16+
source: kube::Error,
17+
},
18+
#[snafu(display("failed to build proxy/configz request"))]
19+
ConfigzRequest {
20+
source: http::Error,
21+
},
22+
23+
#[snafu(display("failed to fetch kubelet config from node {node}"))]
24+
FetchNodeKubeletConfig {
25+
source: kube::Error,
26+
node: String,
27+
},
28+
29+
#[snafu(display("failed to fetch `kubeletconfig` JSON key from configz response"))]
30+
KubeletConfigJsonKey,
31+
32+
#[snafu(display("failed to deserialize kubelet config JSON"))]
33+
KubeletConfigJson {
34+
source: serde_json::Error,
35+
},
36+
37+
#[snafu(display("empty Kubernetes nodes list"))]
38+
EmptyKubernetesNodesList,
39+
}
40+
41+
#[derive(Debug, Deserialize)]
42+
#[serde(rename_all = "camelCase")]
43+
struct KubeletConfig {
44+
cluster_domain: String,
45+
}
46+
47+
impl KubeletConfig {
48+
pub async fn fetch(client: &Client) -> Result<Self, Error> {
49+
let api: Api<Node> = Api::all(client.clone());
50+
let nodes = api.list(&ListParams::default()).await.context(ListNodesSnafu)?;
51+
let node = nodes.iter().next().context(EmptyKubernetesNodesListSnafu)?;
52+
53+
let name = node.name_any();
54+
55+
// Query node stats by issuing a request to the admin endpoint.
56+
// See https://kubernetes.io/docs/reference/instrumentation/node-metrics/
57+
let url = format!("/api/v1/nodes/{}/proxy/configz", name);
58+
let req = http::Request::get(url).body(Default::default()).context(ConfigzRequestSnafu)?;
59+
60+
// Deserialize JSON response as a JSON value. Alternatively, a type that
61+
// implements `Deserialize` can be used.
62+
let resp = client.request::<serde_json::Value>(req).await.context(FetchNodeKubeletConfigSnafu { node: name })?;
63+
64+
// Our JSON value is an object so we can treat it like a dictionary.
65+
let summary = resp
66+
.get("kubeletconfig")
67+
.context(KubeletConfigJsonKeySnafu)?;
68+
69+
// The base JSON representation includes a lot of metrics, including
70+
// container metrics. Use a `NodeMetrics` type to deserialize only the
71+
// values we care about.
72+
serde_json::from_value::<KubeletConfig>(summary.to_owned()).context(KubeletConfigJsonSnafu)
73+
}
74+
75+
}

crates/stackable-operator/src/utils/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod bash;
22
pub mod cluster_info;
33
pub mod crds;
4+
mod kubelet;
45
pub mod logging;
56
mod option;
67
mod url;

0 commit comments

Comments
 (0)