// containerd_grpc_setup.rhai // // This script sets up a Rust project with gRPC connectivity to containerd // Following the steps from the instructions document run("apt-get -y protobuf-compiler "); // Step 1: Set up project directory let project_dir = "/tmp/containerd-rust-client"; print(`Setting up project in: ${project_dir}`); // Clean up any existing directory if exist(project_dir) { print("Found existing project directory, removing it..."); delete(project_dir); } // Create our project directory mkdir(project_dir); // Change to the project directory chdir(project_dir); // Step 2: Clone containerd's gRPC proto files print("Cloning containerd repository to get proto files..."); let git_tree = gittree_new(project_dir); let repos = git_tree.get("https://github.com/containerd/containerd.git"); let repo = repos[0]; print(`Cloned containerd repository to: ${repo.path()}`); // Step 3: Create necessary project files print("Creating Cargo.toml file..."); // Using raw string with # for multiline content let cargo_toml = #" [package] name = "containerd-rust-client" version = "0.1.0" edition = "2021" [dependencies] tonic = "0.11" prost = "0.12" tokio = { version = "1", features = ["full"] } hyper-unix-connector = "0.2.0" tower = "0.4" [build-dependencies] tonic-build = "0.11" "#; file_write("Cargo.toml", cargo_toml); print("Created Cargo.toml file"); // Step 4: Set up build.rs to compile protos print("Creating build.rs file..."); let build_rs = #" fn main() { println!("cargo:rerun-if-changed=containerd/api/services/images/v1/images.proto"); println!("cargo:rerun-if-changed=containerd/api/services/containers/v1/containers.proto"); tonic_build::configure() .build_server(false) .compile( &[ "containerd/api/services/images/v1/images.proto", "containerd/api/services/containers/v1/containers.proto", // Add more proto files as needed ], &[ "containerd", "containerd/api", "containerd/api/types" ], ) .unwrap(); } "#; file_write("build.rs", build_rs); print("Created build.rs file"); // Step 5: Create src directory and main.rs file mkdir("src"); // Create a helper function for Unix socket connection print("Creating src/main.rs file..."); let main_rs = #" use tonic::transport::{Channel, Endpoint, Uri}; use tower::service_fn; use std::convert::TryFrom; // The proto-generated modules will be available after build // use containerd::services::images::v1::{ // images_client::ImagesClient, // GetImageRequest, // }; #[tokio::main] async fn main() -> Result<(), Box> { println!("Connecting to containerd gRPC..."); // Path to containerd socket let socket_path = "/run/containerd/containerd.sock"; // Connect to the Unix socket let channel = unix_socket_channel(socket_path).await?; // Now we'd create a client and use it // let mut client = ImagesClient::new(channel); // let response = client.get(GetImageRequest { // name: "docker.io/library/ubuntu:latest".to_string(), // }).await?; // println!("Image: {:?}", response.into_inner()); println!("Connection to containerd socket established successfully!"); println!("This is a template - uncomment the client code after building."); Ok(()) } // Helper function to connect to Unix socket async fn unix_socket_channel(path: &str) -> Result> { // Use a placeholder URI since Unix sockets don't have URIs let endpoint = Endpoint::try_from("http://[::]:50051")?; // The socket path to connect to let path_to_connect = path.to_string(); // Create a connector function that connects to the Unix socket let channel = endpoint .connect_with_connector(service_fn(move |_: Uri| { let path = path_to_connect.clone(); async move { tokio::net::UnixStream::connect(path) .await .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)) } })) .await?; Ok(channel) } "#; file_write("src/main.rs", main_rs); print("Created src/main.rs file"); // Step 6: Create a README.md file print("Creating README.md file..."); // Using raw string with # for multiline content containing markdown backticks let readme = #"# containerd Rust gRPC Client A Rust client for interacting with containerd via gRPC. ## Prerequisites - Rust and Cargo installed - containerd running on your system ## Building ```bash cargo build ``` ## Running ```bash cargo run ``` ## Features - Connect to containerd via Unix socket - Query image information - Work with containers ## Structure - `src/main.rs` - Example client code - `build.rs` - Proto compilation script "#; file_write("README.md", readme); print("Created README.md file"); // Step 7: Build the project print("Building the project..."); let build_result = run("cargo build"); if build_result.success { print("Project built successfully!"); } else { print(`Build failed with error: ${build_result.stderr}`); } print(` -------------------------------------- 🎉 Setup complete! Project created at: ${project_dir} To use the project: 1. cd ${project_dir} 2. cargo run Note: Make sure containerd is running and the socket exists at /run/containerd/containerd.sock -------------------------------------- `);