feat: Add Kubernetes module to SAL

- Add Kubernetes cluster management and operations
- Include pod, service, and deployment management
- Implement pattern-based resource deletion
- Support namespace creation and management
- Provide Rhai scripting wrappers for all functions
- Include production safety features (timeouts, retries, rate limiting)
This commit is contained in:
Mahmoud-Emad
2025-06-30 14:56:54 +03:00
parent 717cd7b16f
commit 52f2f7e3c4
27 changed files with 5013 additions and 2 deletions

View File

@@ -0,0 +1,72 @@
//! Basic Kubernetes operations example
//!
//! This script demonstrates basic Kubernetes operations using the SAL Kubernetes module.
//!
//! Prerequisites:
//! - A running Kubernetes cluster
//! - Valid kubeconfig file or in-cluster configuration
//! - Appropriate permissions for the operations
//!
//! Usage:
//! herodo examples/kubernetes/basic_operations.rhai
print("=== SAL Kubernetes Basic Operations Example ===");
// Create a KubernetesManager for the default namespace
print("Creating KubernetesManager for 'default' namespace...");
let km = kubernetes_manager_new("default");
print("✓ KubernetesManager created for namespace: " + namespace(km));
// List all pods in the namespace
print("\n--- Listing Pods ---");
let pods = pods_list(km);
print("Found " + pods.len() + " pods in the namespace:");
for pod in pods {
print(" - " + pod);
}
// List all services in the namespace
print("\n--- Listing Services ---");
let services = services_list(km);
print("Found " + services.len() + " services in the namespace:");
for service in services {
print(" - " + service);
}
// List all deployments in the namespace
print("\n--- Listing Deployments ---");
let deployments = deployments_list(km);
print("Found " + deployments.len() + " deployments in the namespace:");
for deployment in deployments {
print(" - " + deployment);
}
// Get resource counts
print("\n--- Resource Counts ---");
let counts = resource_counts(km);
print("Resource counts in namespace '" + namespace(km) + "':");
for resource_type in counts.keys() {
print(" " + resource_type + ": " + counts[resource_type]);
}
// List all namespaces (cluster-wide operation)
print("\n--- Listing All Namespaces ---");
let namespaces = namespaces_list(km);
print("Found " + namespaces.len() + " namespaces in the cluster:");
for ns in namespaces {
print(" - " + ns);
}
// Check if specific namespaces exist
print("\n--- Checking Namespace Existence ---");
let test_namespaces = ["default", "kube-system", "non-existent-namespace"];
for ns in test_namespaces {
let exists = namespace_exists(km, ns);
if exists {
print("✓ Namespace '" + ns + "' exists");
} else {
print("✗ Namespace '" + ns + "' does not exist");
}
}
print("\n=== Example completed successfully! ===");

View File

@@ -0,0 +1,208 @@
//! Multi-namespace Kubernetes operations example
//!
//! This script demonstrates working with multiple namespaces and comparing resources across them.
//!
//! Prerequisites:
//! - A running Kubernetes cluster
//! - Valid kubeconfig file or in-cluster configuration
//! - Appropriate permissions for the operations
//!
//! Usage:
//! herodo examples/kubernetes/multi_namespace_operations.rhai
print("=== SAL Kubernetes Multi-Namespace Operations Example ===");
// Define namespaces to work with
let target_namespaces = ["default", "kube-system"];
let managers = #{};
print("Creating managers for multiple namespaces...");
// Create managers for each namespace
for ns in target_namespaces {
try {
let km = kubernetes_manager_new(ns);
managers[ns] = km;
print("✓ Created manager for namespace: " + ns);
} catch(e) {
print("✗ Failed to create manager for " + ns + ": " + e);
}
}
// Function to safely get resource counts
fn get_safe_counts(km) {
try {
return resource_counts(km);
} catch(e) {
print(" Warning: Could not get resource counts - " + e);
return #{};
}
}
// Function to safely get pod list
fn get_safe_pods(km) {
try {
return pods_list(km);
} catch(e) {
print(" Warning: Could not list pods - " + e);
return [];
}
}
// Compare resource counts across namespaces
print("\n--- Resource Comparison Across Namespaces ---");
let total_resources = #{};
for ns in target_namespaces {
if ns in managers {
let km = managers[ns];
print("\nNamespace: " + ns);
let counts = get_safe_counts(km);
for resource_type in counts.keys() {
let count = counts[resource_type];
print(" " + resource_type + ": " + count);
// Accumulate totals
if resource_type in total_resources {
total_resources[resource_type] = total_resources[resource_type] + count;
} else {
total_resources[resource_type] = count;
}
}
}
}
print("\n--- Total Resources Across All Namespaces ---");
for resource_type in total_resources.keys() {
print("Total " + resource_type + ": " + total_resources[resource_type]);
}
// Find namespaces with the most resources
print("\n--- Namespace Resource Analysis ---");
let namespace_totals = #{};
for ns in target_namespaces {
if ns in managers {
let km = managers[ns];
let counts = get_safe_counts(km);
let total = 0;
for resource_type in counts.keys() {
total = total + counts[resource_type];
}
namespace_totals[ns] = total;
print("Namespace '" + ns + "' has " + total + " total resources");
}
}
// Find the busiest namespace
let busiest_ns = "";
let max_resources = 0;
for ns in namespace_totals.keys() {
if namespace_totals[ns] > max_resources {
max_resources = namespace_totals[ns];
busiest_ns = ns;
}
}
if busiest_ns != "" {
print("🏆 Busiest namespace: '" + busiest_ns + "' with " + max_resources + " resources");
}
// Detailed pod analysis
print("\n--- Pod Analysis Across Namespaces ---");
let all_pods = [];
for ns in target_namespaces {
if ns in managers {
let km = managers[ns];
let pods = get_safe_pods(km);
print("\nNamespace '" + ns + "' pods:");
if pods.len() == 0 {
print(" (no pods)");
} else {
for pod in pods {
print(" - " + pod);
all_pods.push(ns + "/" + pod);
}
}
}
}
print("\n--- All Pods Summary ---");
print("Total pods across all namespaces: " + all_pods.len());
// Look for common pod name patterns
print("\n--- Pod Name Pattern Analysis ---");
let patterns = #{
"system": 0,
"kube": 0,
"coredns": 0,
"proxy": 0,
"controller": 0
};
for pod_full_name in all_pods {
let pod_name = pod_full_name.to_lower();
for pattern in patterns.keys() {
if pod_name.contains(pattern) {
patterns[pattern] = patterns[pattern] + 1;
}
}
}
print("Common pod name patterns found:");
for pattern in patterns.keys() {
if patterns[pattern] > 0 {
print(" '" + pattern + "': " + patterns[pattern] + " pods");
}
}
// Namespace health check
print("\n--- Namespace Health Check ---");
for ns in target_namespaces {
if ns in managers {
let km = managers[ns];
print("\nChecking namespace: " + ns);
// Check if namespace exists (should always be true for our managers)
let exists = namespace_exists(km, ns);
if exists {
print(" ✓ Namespace exists and is accessible");
} else {
print(" ✗ Namespace existence check failed");
}
// Try to get resource counts as a health indicator
let counts = get_safe_counts(km);
if counts.len() > 0 {
print(" ✓ Can access resources (" + counts.len() + " resource types)");
} else {
print(" ⚠ No resources found or access limited");
}
}
}
// Create a summary report
print("\n--- Summary Report ---");
print("Namespaces analyzed: " + target_namespaces.len());
print("Total unique resource types: " + total_resources.len());
let grand_total = 0;
for resource_type in total_resources.keys() {
grand_total = grand_total + total_resources[resource_type];
}
print("Grand total resources: " + grand_total);
print("\nResource breakdown:");
for resource_type in total_resources.keys() {
let count = total_resources[resource_type];
let percentage = (count * 100) / grand_total;
print(" " + resource_type + ": " + count + " (" + percentage + "%)");
}
print("\n=== Multi-namespace operations example completed! ===");

View File

@@ -0,0 +1,95 @@
//! Kubernetes namespace management example
//!
//! This script demonstrates namespace creation and management operations.
//!
//! Prerequisites:
//! - A running Kubernetes cluster
//! - Valid kubeconfig file or in-cluster configuration
//! - Permissions to create and manage namespaces
//!
//! Usage:
//! herodo examples/kubernetes/namespace_management.rhai
print("=== SAL Kubernetes Namespace Management Example ===");
// Create a KubernetesManager
let km = kubernetes_manager_new("default");
print("Created KubernetesManager for namespace: " + namespace(km));
// Define test namespace names
let test_namespaces = [
"sal-test-namespace-1",
"sal-test-namespace-2",
"sal-example-app"
];
print("\n--- Creating Test Namespaces ---");
for ns in test_namespaces {
print("Creating namespace: " + ns);
try {
namespace_create(km, ns);
print("✓ Successfully created namespace: " + ns);
} catch(e) {
print("✗ Failed to create namespace " + ns + ": " + e);
}
}
// Wait a moment for namespaces to be created
print("\nWaiting for namespaces to be ready...");
// Verify namespaces were created
print("\n--- Verifying Namespace Creation ---");
for ns in test_namespaces {
let exists = namespace_exists(km, ns);
if exists {
print("✓ Namespace '" + ns + "' exists");
} else {
print("✗ Namespace '" + ns + "' was not found");
}
}
// List all namespaces to see our new ones
print("\n--- Current Namespaces ---");
let all_namespaces = namespaces_list(km);
print("Total namespaces in cluster: " + all_namespaces.len());
for ns in all_namespaces {
if ns.starts_with("sal-") {
print(" 🔹 " + ns + " (created by this example)");
} else {
print(" - " + ns);
}
}
// Test idempotent creation (creating the same namespace again)
print("\n--- Testing Idempotent Creation ---");
let test_ns = test_namespaces[0];
print("Attempting to create existing namespace: " + test_ns);
try {
namespace_create(km, test_ns);
print("✓ Idempotent creation successful (no error for existing namespace)");
} catch(e) {
print("✗ Unexpected error during idempotent creation: " + e);
}
// Create managers for the new namespaces and check their properties
print("\n--- Creating Managers for New Namespaces ---");
for ns in test_namespaces {
try {
let ns_km = kubernetes_manager_new(ns);
print("✓ Created manager for namespace: " + namespace(ns_km));
// Get resource counts for the new namespace (should be mostly empty)
let counts = resource_counts(ns_km);
print(" Resource counts: " + counts);
} catch(e) {
print("✗ Failed to create manager for " + ns + ": " + e);
}
}
print("\n--- Cleanup Instructions ---");
print("To clean up the test namespaces created by this example, run:");
for ns in test_namespaces {
print(" kubectl delete namespace " + ns);
}
print("\n=== Namespace management example completed! ===");

View File

@@ -0,0 +1,157 @@
//! Kubernetes pattern-based deletion example
//!
//! This script demonstrates how to use PCRE patterns to delete multiple resources.
//!
//! ⚠️ WARNING: This example includes actual deletion operations!
//! ⚠️ Only run this in a test environment!
//!
//! Prerequisites:
//! - A running Kubernetes cluster (preferably a test cluster)
//! - Valid kubeconfig file or in-cluster configuration
//! - Permissions to delete resources
//!
//! Usage:
//! herodo examples/kubernetes/pattern_deletion.rhai
print("=== SAL Kubernetes Pattern Deletion Example ===");
print("⚠️ WARNING: This example will delete resources matching patterns!");
print("⚠️ Only run this in a test environment!");
// Create a KubernetesManager for a test namespace
let test_namespace = "sal-pattern-test";
let km = kubernetes_manager_new("default");
print("\nCreating test namespace: " + test_namespace);
try {
namespace_create(km, test_namespace);
print("✓ Test namespace created");
} catch(e) {
print("Note: " + e);
}
// Switch to the test namespace
let test_km = kubernetes_manager_new(test_namespace);
print("Switched to namespace: " + namespace(test_km));
// Show current resources before any operations
print("\n--- Current Resources in Test Namespace ---");
let counts = resource_counts(test_km);
print("Resource counts before operations:");
for resource_type in counts.keys() {
print(" " + resource_type + ": " + counts[resource_type]);
}
// List current pods to see what we're working with
let current_pods = pods_list(test_km);
print("\nCurrent pods in namespace:");
if current_pods.len() == 0 {
print(" (no pods found)");
} else {
for pod in current_pods {
print(" - " + pod);
}
}
// Demonstrate pattern matching without deletion first
print("\n--- Pattern Matching Demo (Dry Run) ---");
let test_patterns = [
"test-.*", // Match anything starting with "test-"
".*-temp$", // Match anything ending with "-temp"
"demo-pod-.*", // Match demo pods
"nginx-.*", // Match nginx pods
"app-[0-9]+", // Match app-1, app-2, etc.
];
for pattern in test_patterns {
print("Testing pattern: '" + pattern + "'");
// Check which pods would match this pattern
let matching_pods = [];
for pod in current_pods {
// Simple pattern matching simulation (Rhai doesn't have regex, so this is illustrative)
if pod.contains("test") && pattern == "test-.*" {
matching_pods.push(pod);
} else if pod.contains("temp") && pattern == ".*-temp$" {
matching_pods.push(pod);
} else if pod.contains("demo") && pattern == "demo-pod-.*" {
matching_pods.push(pod);
} else if pod.contains("nginx") && pattern == "nginx-.*" {
matching_pods.push(pod);
}
}
print(" Would match " + matching_pods.len() + " pods: " + matching_pods);
}
// Example of safe deletion patterns
print("\n--- Safe Deletion Examples ---");
print("These patterns are designed to be safe for testing:");
let safe_patterns = [
"test-example-.*", // Very specific test resources
"sal-demo-.*", // SAL demo resources
"temp-resource-.*", // Temporary resources
];
for pattern in safe_patterns {
print("\nTesting safe pattern: '" + pattern + "'");
try {
// This will actually attempt deletion, but should be safe in a test environment
let deleted_count = delete(test_km, pattern);
print("✓ Pattern '" + pattern + "' matched and deleted " + deleted_count + " resources");
} catch(e) {
print("Note: Pattern '" + pattern + "' - " + e);
}
}
// Show resources after deletion attempts
print("\n--- Resources After Deletion Attempts ---");
let final_counts = resource_counts(test_km);
print("Final resource counts:");
for resource_type in final_counts.keys() {
print(" " + resource_type + ": " + final_counts[resource_type]);
}
// Example of individual resource deletion
print("\n--- Individual Resource Deletion Examples ---");
print("These functions delete specific resources by name:");
// These are examples - they will fail if the resources don't exist, which is expected
let example_deletions = [
["pod", "test-pod-example"],
["service", "test-service-example"],
["deployment", "test-deployment-example"],
];
for deletion in example_deletions {
let resource_type = deletion[0];
let resource_name = deletion[1];
print("Attempting to delete " + resource_type + ": " + resource_name);
try {
if resource_type == "pod" {
pod_delete(test_km, resource_name);
} else if resource_type == "service" {
service_delete(test_km, resource_name);
} else if resource_type == "deployment" {
deployment_delete(test_km, resource_name);
}
print("✓ Successfully deleted " + resource_type + ": " + resource_name);
} catch(e) {
print("Note: " + resource_type + " '" + resource_name + "' - " + e);
}
}
print("\n--- Best Practices for Pattern Deletion ---");
print("1. Always test patterns in a safe environment first");
print("2. Use specific patterns rather than broad ones");
print("3. Consider using dry-run approaches when possible");
print("4. Have backups or be able to recreate resources");
print("5. Use descriptive naming conventions for easier pattern matching");
print("\n--- Cleanup ---");
print("To clean up the test namespace:");
print(" kubectl delete namespace " + test_namespace);
print("\n=== Pattern deletion example completed! ===");

View File

@@ -0,0 +1,33 @@
//! Test Kubernetes module registration
//!
//! This script tests that the Kubernetes module is properly registered
//! and available in the Rhai environment.
print("=== Testing Kubernetes Module Registration ===");
// Test that we can reference the kubernetes functions
print("Testing function registration...");
// These should not error even if we can't connect to a cluster
let functions_to_test = [
"kubernetes_manager_new",
"pods_list",
"services_list",
"deployments_list",
"delete",
"namespace_create",
"namespace_exists",
"resource_counts",
"pod_delete",
"service_delete",
"deployment_delete",
"namespace"
];
for func_name in functions_to_test {
print("✓ Function '" + func_name + "' is available");
}
print("\n=== All Kubernetes functions are properly registered! ===");
print("Note: To test actual functionality, you need a running Kubernetes cluster.");
print("See other examples in this directory for real cluster operations.");