sal/kubernetes/tests/deployment_env_vars_test.rs
Mahmoud-Emad 6b12001ca2 feat: Add Kubernetes examples and update dependencies
- Add Kubernetes examples demonstrating deployment of various
  applications (PostgreSQL, Redis, generic). This improves the
  documentation and provides practical usage examples.
- Add `tokio` dependency for async examples. This enables the use
  of asynchronous operations in the examples.
- Add `once_cell` dependency for improved resource management in
  Kubernetes module. This allows efficient management of
  singletons and other resources.
2025-07-10 00:40:11 +03:00

385 lines
12 KiB
Rust

//! Tests for deployment creation with environment variables
//!
//! These tests verify the new environment variable functionality in deployments
//! and the enhanced deploy_application method.
use sal_kubernetes::KubernetesManager;
use std::collections::HashMap;
/// Check if Kubernetes integration tests should run
fn should_run_k8s_tests() -> bool {
std::env::var("KUBERNETES_TEST_ENABLED").unwrap_or_default() == "1"
}
#[tokio::test]
async fn test_deployment_create_with_env_vars() {
if !should_run_k8s_tests() {
println!("Skipping Kubernetes integration tests. Set KUBERNETES_TEST_ENABLED=1 to enable.");
return;
}
let km = match KubernetesManager::new("default").await {
Ok(km) => km,
Err(_) => return, // Skip if can't connect
};
// Clean up any existing test deployment
let _ = km.deployment_delete("test-env-deployment").await;
// Create deployment with environment variables
let mut labels = HashMap::new();
labels.insert("app".to_string(), "test-env-app".to_string());
labels.insert("test".to_string(), "env-vars".to_string());
let mut env_vars = HashMap::new();
env_vars.insert("TEST_VAR_1".to_string(), "value1".to_string());
env_vars.insert("TEST_VAR_2".to_string(), "value2".to_string());
env_vars.insert("NODE_ENV".to_string(), "test".to_string());
let result = km
.deployment_create(
"test-env-deployment",
"nginx:latest",
1,
Some(labels),
Some(env_vars),
)
.await;
assert!(
result.is_ok(),
"Failed to create deployment with env vars: {:?}",
result
);
// Verify the deployment was created
let deployment = km.deployment_get("test-env-deployment").await;
assert!(deployment.is_ok(), "Failed to get created deployment");
let deployment = deployment.unwrap();
// Verify environment variables are set in the container spec
if let Some(spec) = &deployment.spec {
if let Some(template) = &spec.template.spec {
if let Some(container) = template.containers.first() {
if let Some(env) = &container.env {
// Check that our environment variables are present
let env_map: HashMap<String, String> = env
.iter()
.filter_map(|e| e.value.as_ref().map(|v| (e.name.clone(), v.clone())))
.collect();
assert_eq!(env_map.get("TEST_VAR_1"), Some(&"value1".to_string()));
assert_eq!(env_map.get("TEST_VAR_2"), Some(&"value2".to_string()));
assert_eq!(env_map.get("NODE_ENV"), Some(&"test".to_string()));
} else {
panic!("No environment variables found in container spec");
}
}
}
}
// Clean up
let _ = km.deployment_delete("test-env-deployment").await;
}
#[tokio::test]
async fn test_pod_create_with_env_vars() {
if !should_run_k8s_tests() {
println!("Skipping Kubernetes integration tests. Set KUBERNETES_TEST_ENABLED=1 to enable.");
return;
}
let km = match KubernetesManager::new("default").await {
Ok(km) => km,
Err(_) => return, // Skip if can't connect
};
// Clean up any existing test pod
let _ = km.pod_delete("test-env-pod").await;
// Create pod with environment variables
let mut env_vars = HashMap::new();
env_vars.insert("NODE_ENV".to_string(), "test".to_string());
env_vars.insert(
"DATABASE_URL".to_string(),
"postgres://localhost:5432/test".to_string(),
);
env_vars.insert("API_KEY".to_string(), "test-api-key-12345".to_string());
let mut labels = HashMap::new();
labels.insert("app".to_string(), "test-env-pod-app".to_string());
labels.insert("test".to_string(), "environment-variables".to_string());
let result = km
.pod_create("test-env-pod", "nginx:latest", Some(labels), Some(env_vars))
.await;
assert!(
result.is_ok(),
"Failed to create pod with env vars: {:?}",
result
);
if let Ok(pod) = result {
let pod_name = pod
.metadata
.name
.as_ref()
.unwrap_or(&"".to_string())
.clone();
assert_eq!(pod_name, "test-env-pod");
println!("✅ Created pod with environment variables: {}", pod_name);
// Verify the pod has the expected environment variables
if let Some(spec) = &pod.spec {
if let Some(container) = spec.containers.first() {
if let Some(env) = &container.env {
let env_names: Vec<String> = env.iter().map(|e| e.name.clone()).collect();
assert!(env_names.contains(&"NODE_ENV".to_string()));
assert!(env_names.contains(&"DATABASE_URL".to_string()));
assert!(env_names.contains(&"API_KEY".to_string()));
println!("✅ Pod has expected environment variables");
}
}
}
}
// Clean up
let _ = km.pod_delete("test-env-pod").await;
}
#[tokio::test]
async fn test_deployment_create_without_env_vars() {
if !should_run_k8s_tests() {
return;
}
let km = match KubernetesManager::new("default").await {
Ok(km) => km,
Err(_) => return,
};
// Clean up any existing test deployment
let _ = km.deployment_delete("test-no-env-deployment").await;
// Create deployment without environment variables
let mut labels = HashMap::new();
labels.insert("app".to_string(), "test-no-env-app".to_string());
let result = km
.deployment_create(
"test-no-env-deployment",
"nginx:latest",
1,
Some(labels),
None, // No environment variables
)
.await;
assert!(
result.is_ok(),
"Failed to create deployment without env vars: {:?}",
result
);
// Verify the deployment was created
let deployment = km.deployment_get("test-no-env-deployment").await;
assert!(deployment.is_ok(), "Failed to get created deployment");
let deployment = deployment.unwrap();
// Verify no environment variables are set
if let Some(spec) = &deployment.spec {
if let Some(template) = &spec.template.spec {
if let Some(container) = template.containers.first() {
// Environment variables should be None or empty
assert!(
container.env.is_none() || container.env.as_ref().unwrap().is_empty(),
"Expected no environment variables, but found some"
);
}
}
}
// Clean up
let _ = km.deployment_delete("test-no-env-deployment").await;
}
#[tokio::test]
async fn test_deploy_application_with_env_vars() {
if !should_run_k8s_tests() {
return;
}
let km = match KubernetesManager::new("default").await {
Ok(km) => km,
Err(_) => return,
};
// Clean up any existing resources
let _ = km.deployment_delete("test-app-env").await;
let _ = km.service_delete("test-app-env").await;
// Deploy application with both labels and environment variables
let mut labels = HashMap::new();
labels.insert("app".to_string(), "test-app-env".to_string());
labels.insert("tier".to_string(), "backend".to_string());
let mut env_vars = HashMap::new();
env_vars.insert(
"DATABASE_URL".to_string(),
"postgres://localhost:5432/test".to_string(),
);
env_vars.insert("API_KEY".to_string(), "test-api-key".to_string());
env_vars.insert("LOG_LEVEL".to_string(), "debug".to_string());
let result = km
.deploy_application(
"test-app-env",
"nginx:latest",
2,
80,
Some(labels),
Some(env_vars),
)
.await;
assert!(
result.is_ok(),
"Failed to deploy application with env vars: {:?}",
result
);
// Verify both deployment and service were created
let deployment = km.deployment_get("test-app-env").await;
assert!(deployment.is_ok(), "Deployment should be created");
let service = km.service_get("test-app-env").await;
assert!(service.is_ok(), "Service should be created");
// Verify environment variables in deployment
let deployment = deployment.unwrap();
if let Some(spec) = &deployment.spec {
if let Some(template) = &spec.template.spec {
if let Some(container) = template.containers.first() {
if let Some(env) = &container.env {
let env_map: HashMap<String, String> = env
.iter()
.filter_map(|e| e.value.as_ref().map(|v| (e.name.clone(), v.clone())))
.collect();
assert_eq!(
env_map.get("DATABASE_URL"),
Some(&"postgres://localhost:5432/test".to_string())
);
assert_eq!(env_map.get("API_KEY"), Some(&"test-api-key".to_string()));
assert_eq!(env_map.get("LOG_LEVEL"), Some(&"debug".to_string()));
}
}
}
}
// Clean up
let _ = km.deployment_delete("test-app-env").await;
let _ = km.service_delete("test-app-env").await;
}
#[tokio::test]
async fn test_deploy_application_cleanup_existing_resources() {
if !should_run_k8s_tests() {
return;
}
let km = match KubernetesManager::new("default").await {
Ok(km) => km,
Err(_) => {
println!("Skipping test - no Kubernetes cluster available");
return;
}
};
let app_name = "test-cleanup-app";
// Clean up any existing resources first to ensure clean state
let _ = km.deployment_delete(app_name).await;
let _ = km.service_delete(app_name).await;
// Wait a moment for cleanup to complete
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
// First deployment
let result = km
.deploy_application(app_name, "nginx:latest", 1, 80, None, None)
.await;
if result.is_err() {
println!("Skipping test - cluster connection unstable: {:?}", result);
return;
}
// Verify resources exist (with graceful handling)
let deployment_exists = km.deployment_get(app_name).await.is_ok();
let service_exists = km.service_get(app_name).await.is_ok();
if !deployment_exists || !service_exists {
println!("Skipping test - resources not created properly");
let _ = km.deployment_delete(app_name).await;
let _ = km.service_delete(app_name).await;
return;
}
// Second deployment with different configuration (should replace the first)
let mut env_vars = HashMap::new();
env_vars.insert("VERSION".to_string(), "2.0".to_string());
let result = km
.deploy_application(app_name, "nginx:alpine", 2, 80, None, Some(env_vars))
.await;
if result.is_err() {
println!(
"Skipping verification - second deployment failed: {:?}",
result
);
let _ = km.deployment_delete(app_name).await;
let _ = km.service_delete(app_name).await;
return;
}
// Verify resources still exist (replaced, not duplicated)
let deployment = km.deployment_get(app_name).await;
if deployment.is_err() {
println!("Skipping verification - deployment not found after replacement");
let _ = km.deployment_delete(app_name).await;
let _ = km.service_delete(app_name).await;
return;
}
// Verify the new configuration
let deployment = deployment.unwrap();
if let Some(spec) = &deployment.spec {
assert_eq!(spec.replicas, Some(2), "Replicas should be updated to 2");
if let Some(template) = &spec.template.spec {
if let Some(container) = template.containers.first() {
assert_eq!(
container.image,
Some("nginx:alpine".to_string()),
"Image should be updated"
);
if let Some(env) = &container.env {
let has_version = env
.iter()
.any(|e| e.name == "VERSION" && e.value == Some("2.0".to_string()));
assert!(has_version, "Environment variable VERSION should be set");
}
}
}
}
// Clean up
let _ = km.deployment_delete(app_name).await;
let _ = km.service_delete(app_name).await;
}