1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use crate::{
    api::{Api, Resource},
    Error, Result,
};
use k8s_openapi::api::core::v1::Node;
use kube_core::util::Restart;
use serde::de::DeserializeOwned;

k8s_openapi::k8s_if_ge_1_19! {
    mod csr;
}

impl<K> Api<K>
where
    K: Restart + Resource + DeserializeOwned,
{
    /// Trigger a restart of a Resource.
    pub async fn restart(&self, name: &str) -> Result<K> {
        let mut req = self.request.restart(name).map_err(Error::BuildRequest)?;
        req.extensions_mut().insert("restart");
        self.client.request::<K>(req).await
    }
}

impl Api<Node> {
    /// Cordon a Node.
    pub async fn cordon(&self, name: &str) -> Result<Node> {
        let mut req = self.request.cordon(name).map_err(Error::BuildRequest)?;
        req.extensions_mut().insert("cordon");
        self.client.request::<Node>(req).await
    }

    /// Uncordon a Node.
    pub async fn uncordon(&self, name: &str) -> Result<Node> {
        let mut req = self.request.uncordon(name).map_err(Error::BuildRequest)?;
        req.extensions_mut().insert("cordon");
        self.client.request::<Node>(req).await
    }
}

// Tests that require a cluster and the complete feature set
// Can be run with `cargo test -p kube-client --lib -- --ignored`
#[cfg(test)]
#[cfg(all(feature = "client"))]
mod test {
    use crate::{
        api::{Api, DeleteParams, ListParams, PostParams},
        Client,
    };
    use k8s_openapi::api::core::v1::Node;
    use serde_json::json;

    #[tokio::test]
    #[ignore] // needs kubeconfig
    async fn node_cordon_and_uncordon_works() -> Result<(), Box<dyn std::error::Error>> {
        let client = Client::try_default().await?;

        let node_name = "fakenode";
        let fake_node = serde_json::from_value(json!({
        "apiVersion": "v1",
        "kind": "Node",
        "metadata": {
            "name": node_name,
            },
        }))?;

        let nodes: Api<Node> = Api::all(client.clone());
        nodes.create(&PostParams::default(), &fake_node).await?;

        let schedulables = ListParams::default().fields("spec.unschedulable==false");
        let nodes_init = nodes.list(&schedulables).await?;
        let num_nodes_before_cordon = nodes_init.items.len();

        nodes.cordon(node_name).await?;
        let nodes_after_cordon = nodes.list(&schedulables).await?;
        assert_eq!(nodes_after_cordon.items.len(), num_nodes_before_cordon - 1);

        nodes.uncordon(node_name).await?;
        let nodes_after_uncordon = nodes.list(&schedulables).await?;
        assert_eq!(nodes_after_uncordon.items.len(), num_nodes_before_cordon);
        nodes.delete(node_name, &DeleteParams::default()).await?;
        Ok(())
    }
}