//! CRUD operations tests for SAL Kubernetes //! //! These tests verify that all Create, Read, Update, Delete operations work correctly. #[cfg(test)] mod crud_tests { 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_complete_crud_operations() { if !should_run_k8s_tests() { println!("Skipping CRUD test. Set KUBERNETES_TEST_ENABLED=1 to enable."); return; } println!("šŸ” Testing complete CRUD operations..."); // Create a test namespace for our operations let test_namespace = "sal-crud-test"; let km = KubernetesManager::new("default").await .expect("Should connect to cluster"); // Clean up any existing test namespace let _ = km.namespace_delete(test_namespace).await; tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; // CREATE operations println!("\n=== CREATE Operations ==="); // 1. Create namespace km.namespace_create(test_namespace).await .expect("Should create test namespace"); println!("āœ… Created namespace: {}", test_namespace); // Switch to test namespace let test_km = KubernetesManager::new(test_namespace).await .expect("Should connect to test namespace"); // 2. Create ConfigMap let mut config_data = HashMap::new(); config_data.insert("app.properties".to_string(), "debug=true\nport=8080".to_string()); config_data.insert("config.yaml".to_string(), "key: value\nenv: test".to_string()); let configmap = test_km.configmap_create("test-config", config_data).await .expect("Should create ConfigMap"); println!("āœ… Created ConfigMap: {}", configmap.metadata.name.unwrap_or_default()); // 3. Create Secret let mut secret_data = HashMap::new(); secret_data.insert("username".to_string(), "testuser".to_string()); secret_data.insert("password".to_string(), "secret123".to_string()); let secret = test_km.secret_create("test-secret", secret_data, None).await .expect("Should create Secret"); println!("āœ… Created Secret: {}", secret.metadata.name.unwrap_or_default()); // 4. Create Pod let mut pod_labels = HashMap::new(); pod_labels.insert("app".to_string(), "test-app".to_string()); pod_labels.insert("version".to_string(), "v1".to_string()); let pod = test_km.pod_create("test-pod", "nginx:alpine", Some(pod_labels.clone())).await .expect("Should create Pod"); println!("āœ… Created Pod: {}", pod.metadata.name.unwrap_or_default()); // 5. Create Service let service = test_km.service_create("test-service", pod_labels.clone(), 80, Some(80)).await .expect("Should create Service"); println!("āœ… Created Service: {}", service.metadata.name.unwrap_or_default()); // 6. Create Deployment let deployment = test_km.deployment_create("test-deployment", "nginx:alpine", 2, Some(pod_labels)).await .expect("Should create Deployment"); println!("āœ… Created Deployment: {}", deployment.metadata.name.unwrap_or_default()); // READ operations println!("\n=== READ Operations ==="); // List all resources let pods = test_km.pods_list().await.expect("Should list pods"); println!("āœ… Listed {} pods", pods.len()); let services = test_km.services_list().await.expect("Should list services"); println!("āœ… Listed {} services", services.len()); let deployments = test_km.deployments_list().await.expect("Should list deployments"); println!("āœ… Listed {} deployments", deployments.len()); let configmaps = test_km.configmaps_list().await.expect("Should list configmaps"); println!("āœ… Listed {} configmaps", configmaps.len()); let secrets = test_km.secrets_list().await.expect("Should list secrets"); println!("āœ… Listed {} secrets", secrets.len()); // Get specific resources let pod = test_km.pod_get("test-pod").await.expect("Should get pod"); println!("āœ… Retrieved pod: {}", pod.metadata.name.unwrap_or_default()); let service = test_km.service_get("test-service").await.expect("Should get service"); println!("āœ… Retrieved service: {}", service.metadata.name.unwrap_or_default()); let deployment = test_km.deployment_get("test-deployment").await.expect("Should get deployment"); println!("āœ… Retrieved deployment: {}", deployment.metadata.name.unwrap_or_default()); // Resource counts let counts = test_km.resource_counts().await.expect("Should get resource counts"); println!("āœ… Resource counts: {:?}", counts); // DELETE operations println!("\n=== DELETE Operations ==="); // Delete individual resources test_km.pod_delete("test-pod").await.expect("Should delete pod"); println!("āœ… Deleted pod"); test_km.service_delete("test-service").await.expect("Should delete service"); println!("āœ… Deleted service"); test_km.deployment_delete("test-deployment").await.expect("Should delete deployment"); println!("āœ… Deleted deployment"); test_km.configmap_delete("test-config").await.expect("Should delete configmap"); println!("āœ… Deleted configmap"); test_km.secret_delete("test-secret").await.expect("Should delete secret"); println!("āœ… Deleted secret"); // Verify resources are deleted let final_counts = test_km.resource_counts().await.expect("Should get final resource counts"); println!("āœ… Final resource counts: {:?}", final_counts); // Delete the test namespace km.namespace_delete(test_namespace).await.expect("Should delete test namespace"); println!("āœ… Deleted test namespace"); println!("\nšŸŽ‰ All CRUD operations completed successfully!"); } #[tokio::test] async fn test_error_handling_in_crud() { if !should_run_k8s_tests() { println!("Skipping CRUD error handling test. Set KUBERNETES_TEST_ENABLED=1 to enable."); return; } println!("šŸ” Testing error handling in CRUD operations..."); let km = KubernetesManager::new("default").await .expect("Should connect to cluster"); // Test creating resources with invalid names let result = km.pod_create("", "nginx", None).await; assert!(result.is_err(), "Should fail with empty pod name"); println!("āœ… Empty pod name properly rejected"); // Test getting non-existent resources let result = km.pod_get("non-existent-pod").await; assert!(result.is_err(), "Should fail to get non-existent pod"); println!("āœ… Non-existent pod properly handled"); // Test deleting non-existent resources let result = km.service_delete("non-existent-service").await; assert!(result.is_err(), "Should fail to delete non-existent service"); println!("āœ… Non-existent service deletion properly handled"); println!("āœ… Error handling in CRUD operations is robust"); } }