Skip to content

Commit

Permalink
docs(testcontainers#200): add k3s pod api example
Browse files Browse the repository at this point in the history
  • Loading branch information
bbortt committed Sep 3, 2024
1 parent b09e026 commit 660cb62
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ tokio-util = { version = "0.7.10", features = ["compat"] }
zookeeper-client = { version = "0.8.0" }
kube = { version = "0.90.0", default-features = false, features = [
"client",
"runtime",
"rustls-tls",
] }
k8s-openapi = { version = "0.21.1", features = ["v1_29"] }
Expand Down
86 changes: 81 additions & 5 deletions src/k3s/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,10 @@ mod tests {
use std::env::temp_dir;

use k8s_openapi::api::core::v1::Pod;
use kube::{
api::ListParams,
config::{KubeConfigOptions, Kubeconfig},
Api, Config, ResourceExt,
};
use kube::config::{KubeConfigOptions, Kubeconfig};
use kube::{api::{Api, DeleteParams, ListParams, Patch, PatchParams, PostParams, ResourceExt}, runtime::wait::{await_condition, conditions::is_pod_running}, Config};
use rustls::crypto::CryptoProvider;
use serde_json::json;
use testcontainers::{runners::AsyncRunner, ContainerAsync, ImageExt};

use super::*;
Expand Down Expand Up @@ -224,6 +222,84 @@ mod tests {
Ok(())
}

// Based on: https://github.com/kube-rs/kube/blob/main/examples/pod_api.rs
#[tokio::test]
async fn pod_api() -> Result<(), Box<dyn std::error::Error + 'static>> {
let conf_dir = temp_dir();
let k3s = K3s::default()
.with_conf_mount(&conf_dir)
.with_privileged(true)
.with_userns_mode("host");

let k3s_container = k3s.start().await?;

let client = get_kube_client(&k3s_container).await?;

// Manage pods
let pods: Api<Pod> = Api::default_namespaced(client);

// Create Pod blog
let p: Pod = serde_json::from_value(json!({
"apiVersion": "v1",
"kind": "Pod",
"metadata": { "name": "blog" },
"spec": {
"containers": [{
"name": "blog",
"image": "clux/blog:0.1.0"
}],
}
}))?;

let pp = PostParams::default();
match pods.create(&pp, &p).await {
Ok(o) => {
let name = o.name_any();
assert_eq!(p.name_any(), name);
}
Err(kube::Error::Api(ae)) => assert_eq!(ae.code, 409), // if you skipped delete, for instance
Err(e) => return Err(e.into()), // any other case is probably bad
}

// Watch it phase for a few seconds
let establish = await_condition(pods.clone(), "blog", is_pod_running());
let _ = tokio::time::timeout(std::time::Duration::from_secs(15), establish).await?;

// Verify we can get it
let p1cpy = pods.get("blog").await?;
if let Some(spec) = &p1cpy.spec {
assert_eq!(spec.containers[0].name, "blog");
}

// Replace its spec
let patch = json!({
"metadata": {
"resourceVersion": p1cpy.resource_version(),
},
"spec": {
"activeDeadlineSeconds": 5
}
});
let patchparams = PatchParams::default();
let p_patched = pods
.patch("blog", &patchparams, &Patch::Merge(&patch))
.await?;
assert_eq!(p_patched.spec.unwrap().active_deadline_seconds, Some(5));

let lp = ListParams::default().fields(&format!("metadata.name={}", "blog")); // only want results for our pod
for p in pods.list(&lp).await? {
println!("Found Pod: {}", p.name_any());
}

// Delete it
let dp = DeleteParams::default();
pods.delete("blog", &dp).await?.map_left(|pdel| {
assert_eq!(pdel.name_any(), "blog");
});

Ok(())
}

pub async fn get_kube_client(
container: &ContainerAsync<K3s>,
) -> Result<kube::Client, Box<dyn std::error::Error + 'static>> {
Expand Down

0 comments on commit 660cb62

Please sign in to comment.