# Kubernetes Module (`herolib_virt::kubernetes`)
## Overview
The Kubernetes module provides a comprehensive Rust interface for managing Kubernetes clusters. It offers namespace-scoped resource management, pod lifecycle operations, service deployment, and advanced features like Traefik configuration and container image building.
This is a **Rust-first** module with full type safety and async/await support for production Kubernetes operations.
## Quick Start
### Basic Usage
```rust
use herolib_virt::kubernetes::KubernetesManager;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a manager for a namespace
let km = KubernetesManager::new("my-namespace").await?;
// List all pods
let pods = km.pods_list().await?;
for pod in pods {
println!("Pod: {:?}", pod.metadata.name);
}
Ok(())
}
```
### Running Integration Tests
The module includes comprehensive integration tests in the `01_basic_operations.rs` example:
```bash
cd packages/virt
cargo run --example 01_basic_operations --features kubernetes
```
This example creates 5 Kubernetes resources and runs 14 verification tests to ensure everything works correctly.
## Core Components
### 1. KubernetesManager
The primary entry point for all Kubernetes operations. Each instance operates on a single namespace.
```rust
// Create a manager for a namespace
let km = KubernetesManager::new("my-namespace").await?;
// Get the namespace this manager operates on
let namespace = km.namespace();
println!("Operating on namespace: {}", namespace);
// Get the Kubernetes client
let client = km.client();
// Get the configuration
let config = km.config();
```
### 2. Resource Management
#### Pods
```rust
use std::collections::BTreeMap;
// Create a simple pod
let labels = [("app".to_string(), "my-app".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.pod_create("my-pod", "nginx:alpine", labels.clone()).await?;
// Create a pod with environment variables
let env_vars = [("MY_VAR".to_string(), "my-value".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.pod_create_with_env("my-pod", "nginx:alpine", labels, env_vars).await?;
// List all pods in the namespace
let pods = km.pods_list().await?;
for pod in pods {
println!("Pod: {:?}", pod.metadata.name);
}
// Get a specific pod
let pod = km.pod_get("my-pod").await?;
println!("Pod image: {:?}", pod.spec.unwrap().containers[0].image);
// Delete a pod
km.pod_delete("my-pod").await?;
```
#### Services
```rust
use std::collections::BTreeMap;
// Create a service
let selector = [("app".to_string(), "my-app".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.service_create("my-service", selector, 80, 8080).await?;
// List services
let services = km.services_list().await?;
for service in services {
println!("Service: {:?}", service.metadata.name);
}
// Get a specific service
let svc = km.service_get("my-service").await?;
// Delete a service
km.service_delete("my-service").await?;
```
#### Deployments
```rust
use std::collections::BTreeMap;
// Create a deployment
let labels = [("app".to_string(), "my-app".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
let env_vars = [("LOG_LEVEL".to_string(), "info".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.deployment_create(
"my-deployment",
"nginx:alpine",
3,
labels,
env_vars,
).await?;
// List deployments
let deployments = km.deployments_list().await?;
for deployment in deployments {
println!("Deployment: {:?}", deployment.metadata.name);
}
// Get a specific deployment
let deploy = km.deployment_get("my-deployment").await?;
// Delete a deployment
km.deployment_delete("my-deployment").await?;
```
#### ConfigMaps
```rust
use std::collections::BTreeMap;
// Create a ConfigMap
let config_data = [
("config.json".to_string(), r#"{"key": "value"}"#.to_string()),
("settings.yaml".to_string(), "debug: true".to_string()),
]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.configmap_create("my-config", config_data).await?;
// List ConfigMaps
let configmaps = km.configmaps_list().await?;
for cm in configmaps {
println!("ConfigMap: {:?}", cm.metadata.name);
}
// Get a specific ConfigMap
let config = km.configmap_get("my-config").await?;
if let Some(data) = config.data {
for (key, value) in data {
println!("Key: {}, Value: {}", key, value);
}
}
// Delete a ConfigMap
km.configmap_delete("my-config").await?;
```
#### Secrets
```rust
use std::collections::BTreeMap;
// Create a Secret
let secret_data = [
("username".to_string(), "admin".to_string()),
("password".to_string(), "secret123".to_string()),
]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.secret_create("my-secret", secret_data, "Opaque").await?;
// List Secrets
let secrets = km.secrets_list().await?;
for secret in secrets {
println!("Secret: {:?}", secret.metadata.name);
}
// Get a specific Secret
let secret = km.secret_get("my-secret").await?;
if let Some(data) = secret.data {
for (key, _value) in data {
println!("Secret key: {}", key);
}
}
// Delete a Secret
km.secret_delete("my-secret").await?;
```
### 3. Namespace Management
```rust
let km = KubernetesManager::new("default").await?;
// Create a namespace (idempotent)
km.namespace_create("my-new-namespace").await?;
// Check if namespace exists
let exists = km.namespace_exists("my-new-namespace").await?;
if exists {
println!("Namespace exists!");
}
// List all namespaces
let namespaces = km.namespaces_list().await?;
for ns in namespaces {
println!("Namespace: {:?}", ns.metadata.name);
}
// Reset a namespace (delete and recreate)
km.namespace_reset("my-namespace").await?;
// Delete a namespace
km.namespace_delete("my-new-namespace").await?;
```
### 4. Pattern-Based Deletion
Delete resources matching PCRE regex patterns:
```rust
// Delete all resources matching a pattern
let deleted_count = km.delete("test-.*").await?;
println!("Deleted {} resources", deleted_count);
// Delete pods matching a pattern
km.delete("my-app-pod-.*").await?;
```
### 5. Service Connection Info
Get connection information for services:
```rust
let km = KubernetesManager::new("my-namespace").await?;
// Get service connection info
let info = km.service_connection_info("my-service").await?;
// Access connection properties
println!("Service: {}", info.name);
println!("Namespace: {}", info.namespace);
println!("Hostname: {}", info.hostname);
println!("Cluster IP: {}", info.cluster_ip);
println!("Service Type: {}", info.service_type);
// Get ports
let ports = &info.ports;
let node_ports = &info.node_ports;
// Get connection strings
let conn_str = info.connection_string();
let host_conn = info.host_accessible_hostname();
let localhost_conn = info.localhost_connection_string();
println!("Connection: {}", conn_str);
```
### 6. Resource Counts
```rust
let counts = km.resource_counts().await?;
println!("Pods: {}", counts.get("pods").unwrap_or(&0));
println!("Services: {}", counts.get("services").unwrap_or(&0));
println!("Deployments: {}", counts.get("deployments").unwrap_or(&0));
```
### 7. Deploy Application (Convenience Function)
Deploy a complete application with deployment and service:
```rust
use std::collections::BTreeMap;
let labels = [("app".to_string(), "my-app".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
let env_vars = [("DATABASE_URL".to_string(), "postgres://localhost:5432/mydb".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.deploy_application(
"my-app",
"my-image:latest",
3,
8080,
labels,
env_vars,
).await?;
```
## Fluent API (Builder Pattern)
The module includes a fluent builder API for more ergonomic resource creation:
```rust
use herolib_virt::kubernetes::KubernetesContext;
// Create a pod using the fluent API
KubernetesContext::pod("my-pod", "nginx:alpine")
.label("app", "my-app")
.label("environment", "development")
.apply(&km)
.await?;
// Create a service using the fluent API
KubernetesContext::service("my-service")
.selector("app", "my-app")
.port(80, 8080)
.apply(&km)
.await?;
// Create a ConfigMap using the fluent API
KubernetesContext::configmap("my-config")
.data("config.json", r#"{"key": "value"}"#)
.apply(&km)
.await?;
// Create a Secret using the fluent API
KubernetesContext::secret("my-secret")
.data("username", "admin")
.data("password", "secret123")
.secret_type("Opaque")
.apply(&km)
.await?;
// Create a namespace using the fluent API
KubernetesContext::namespace("my-namespace")
.apply(&km)
.await?;
```
## Traefik Configuration
Configure Traefik IngressRoutes, Middlewares, and TLS options:
### HTTP Routes
```rust
use herolib_virt::kubernetes::HttpRoute;
let route = HttpRoute::new("my-app-route", "production")
.hostname("app.example.com")
.path_prefix("/api")
.service("my-service", 8080)
.middleware("auth-middleware")
.priority(100)
.build();
// TODO: Apply the route to the cluster
```
## KubeBuilder: Build Container Images in Kubernetes
Build container images inside Kubernetes using Buildah:
```rust
use herolib_virt::kubernetes::BuildMachine;
// Create a build machine configuration
let machine = BuildMachine::new("build-namespace", "my-builder");
// Provision the build machine (creates a pod)
let handle = machine.provision().await?;
println!("Pod name: {}", handle.pod_name);
println!("Namespace: {}", handle.namespace);
// Execute commands in the build machine
let result = handle.exec(&["ls", "-la"]).await?;
if result.success {
println!("Output: {}", result.stdout);
}
// Run buildah commands directly
let buildah_result = handle.buildah(&["images"]).await?;
println!("Images: {}", buildah_result.stdout);
// Destroy the build machine when done
handle.destroy().await?;
```
## Error Handling
```rust
use herolib_virt::kubernetes::KubernetesResult;
// All operations return KubernetesResult<T>
match km.pod_get("my-pod").await {
Ok(pod) => println!("Found pod: {:?}", pod),
Err(e) => eprintln!("Error: {:?}", e),
}
// Or use the ? operator in async functions
let pod = km.pod_get("my-pod").await?;
```
## Production Safety Features
The KubernetesManager includes built-in production safety features:
- **Configurable Timeouts**: All operations have configurable timeouts
- **Exponential Backoff Retry**: Automatic retries with exponential backoff for transient failures
- **Rate Limiting**: Built-in rate limiting to prevent API overload
- **Cluster Validation**: Validates cluster connectivity on manager creation
- **Name Normalization**: RFC 1123 compliant name validation through fluent API
## Integration Testing
The module includes comprehensive integration tests. See the example below for how to test your Kubernetes operations:
### Running Tests
```bash
cd packages/virt
cargo run --example 01_basic_operations --features kubernetes
```
### Test Coverage
The example creates and verifies:
- ✅ Namespace creation and deletion
- ✅ Pod creation and property verification
- ✅ Service creation and connection info
- ✅ ConfigMap creation and data integrity
- ✅ Secret creation and data verification
- ✅ RFC 1123 name normalization
Each verification is a separate test within the example. All tests pass on a live Kubernetes cluster.
## API Reference
### KubernetesManager Methods
| `new(namespace)` | Create a new manager for a namespace |
| `with_config(namespace, config)` | Create a manager with custom configuration |
| `namespace()` | Get the namespace this manager operates on |
| `client()` | Get the underlying Kubernetes client |
| `config()` | Get the manager configuration |
| `pods_list()` | List all pods in the namespace |
| `pod_create(name, image, labels)` | Create a pod |
| `pod_create_with_env(name, image, labels, env)` | Create a pod with environment variables |
| `pod_get(name)` | Get a specific pod |
| `pod_delete(name)` | Delete a specific pod |
| `services_list()` | List all services in the namespace |
| `service_create(name, selector, port, target_port)` | Create a service |
| `service_create_lb(name, selector, port, target_port)` | Create a LoadBalancer service |
| `service_get(name)` | Get a specific service |
| `service_delete(name)` | Delete a specific service |
| `deployments_list()` | List all deployments in the namespace |
| `deployment_create(name, image, replicas, labels, env)` | Create a deployment |
| `deployment_get(name)` | Get a specific deployment |
| `deployment_delete(name)` | Delete a specific deployment |
| `configmaps_list()` | List all ConfigMaps in the namespace |
| `configmap_create(name, data)` | Create a ConfigMap |
| `configmap_get(name)` | Get a specific ConfigMap |
| `configmap_delete(name)` | Delete a specific ConfigMap |
| `secrets_list()` | List all Secrets in the namespace |
| `secret_create(name, data, type)` | Create a Secret |
| `secret_get(name)` | Get a specific Secret |
| `secret_delete(name)` | Delete a specific Secret |
| `delete(pattern)` | Delete resources matching PCRE pattern |
| `namespaces_list()` | List all namespaces in the cluster |
| `namespace_create(name)` | Create a namespace (idempotent) |
| `namespace_exists(name)` | Check if a namespace exists |
| `namespace_delete(name)` | Delete a namespace |
| `namespace_reset(name)` | Delete and recreate a namespace |
| `resource_counts()` | Get counts of all resources |
| `deploy_application(name, image, replicas, port, labels, env)` | Deploy a full application |
| `service_connection_info(name)` | Get connection info for a service |
### Fluent API Methods
#### Pod Builder
```rust
KubernetesContext::pod(name, image)
.label(key, value)
.apply(&km)
.await?
```
#### Service Builder
```rust
KubernetesContext::service(name)
.selector(key, value)
.port(port, target_port)
.apply(&km)
.await?
```
#### ConfigMap Builder
```rust
KubernetesContext::configmap(name)
.data(key, value)
.apply(&km)
.await?
```
#### Secret Builder
```rust
KubernetesContext::secret(name)
.data(key, value)
.secret_type(type)
.apply(&km)
.await?
```
#### Namespace Builder
```rust
KubernetesContext::namespace(name)
.apply(&km)
.await?
```
## Complete Example: Deploying a Web Application
```rust
use herolib_virt::kubernetes::KubernetesManager;
use std::collections::BTreeMap;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Setup namespace
let default_km = KubernetesManager::new("default").await?;
default_km.namespace_create("my-app").await?;
// Switch to app namespace
let km = KubernetesManager::new("my-app").await?;
// Deploy the application
let labels = [("app".to_string(), "web-frontend".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
let env = [("API_URL".to_string(), "http://api-service:8080".to_string())]
.iter()
.cloned()
.collect::<BTreeMap<_, _>>();
km.deploy_application(
"web-frontend",
"myregistry/frontend:v1.0",
3,
80,
labels,
env,
).await?;
// Check deployment status
let counts = km.resource_counts().await?;
println!("Deployed resources:");
println!(" Pods: {}", counts.get("pods").unwrap_or(&0));
println!(" Services: {}", counts.get("services").unwrap_or(&0));
println!(" Deployments: {}", counts.get("deployments").unwrap_or(&0));
// Get service connection info
let svc_info = km.service_connection_info("web-frontend").await?;
println!("Service available at: {}", svc_info.connection_string());
Ok(())
}
```
## See Also
- [Integration Tests](../../../../../packages/virt/examples/01_basic_operations.rs) - Comprehensive example with 14 tests
- [Kubernetes Testing Quick Start](../../../../../KUBERNETES_TEST_QUICK_START.md) - How to run the tests
- [Kubernetes Testing Complete](../../../../../KUBERNETES_TESTING_COMPLETE.md) - Full testing documentation
- [Buildah Module](../buildah/README.md) - Container image building