This commit is contained in:
2025-08-05 15:33:03 +02:00
parent 7856fc0a4e
commit 0c02d0e99f
326 changed files with 334 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
//! Configuration for production safety features
use std::time::Duration;
/// Configuration for Kubernetes operations with production safety features
#[derive(Debug, Clone)]
pub struct KubernetesConfig {
/// Timeout for individual API operations
pub operation_timeout: Duration,
/// Maximum number of retry attempts for failed operations
pub max_retries: u32,
/// Base delay for exponential backoff retry strategy
pub retry_base_delay: Duration,
/// Maximum delay between retries
pub retry_max_delay: Duration,
/// Rate limiting: maximum requests per second
pub rate_limit_rps: u32,
/// Rate limiting: burst capacity
pub rate_limit_burst: u32,
}
impl Default for KubernetesConfig {
fn default() -> Self {
Self {
// Conservative timeout for production
operation_timeout: Duration::from_secs(30),
// Reasonable retry attempts
max_retries: 3,
// Exponential backoff starting at 1 second
retry_base_delay: Duration::from_secs(1),
// Maximum 30 seconds between retries
retry_max_delay: Duration::from_secs(30),
// Conservative rate limiting: 10 requests per second
rate_limit_rps: 10,
// Allow small bursts
rate_limit_burst: 20,
}
}
}
impl KubernetesConfig {
/// Create a new configuration with custom settings
pub fn new() -> Self {
Self::default()
}
/// Set operation timeout
pub fn with_timeout(mut self, timeout: Duration) -> Self {
self.operation_timeout = timeout;
self
}
/// Set retry configuration
pub fn with_retries(mut self, max_retries: u32, base_delay: Duration, max_delay: Duration) -> Self {
self.max_retries = max_retries;
self.retry_base_delay = base_delay;
self.retry_max_delay = max_delay;
self
}
/// Set rate limiting configuration
pub fn with_rate_limit(mut self, rps: u32, burst: u32) -> Self {
self.rate_limit_rps = rps;
self.rate_limit_burst = burst;
self
}
/// Create configuration optimized for high-throughput environments
pub fn high_throughput() -> Self {
Self {
operation_timeout: Duration::from_secs(60),
max_retries: 5,
retry_base_delay: Duration::from_millis(500),
retry_max_delay: Duration::from_secs(60),
rate_limit_rps: 50,
rate_limit_burst: 100,
}
}
/// Create configuration optimized for low-latency environments
pub fn low_latency() -> Self {
Self {
operation_timeout: Duration::from_secs(10),
max_retries: 2,
retry_base_delay: Duration::from_millis(100),
retry_max_delay: Duration::from_secs(5),
rate_limit_rps: 20,
rate_limit_burst: 40,
}
}
/// Create configuration for development/testing
pub fn development() -> Self {
Self {
operation_timeout: Duration::from_secs(120),
max_retries: 1,
retry_base_delay: Duration::from_millis(100),
retry_max_delay: Duration::from_secs(2),
rate_limit_rps: 100,
rate_limit_burst: 200,
}
}
}

View File

@@ -0,0 +1,85 @@
//! Error types for SAL Kubernetes operations
use thiserror::Error;
/// Errors that can occur during Kubernetes operations
#[derive(Error, Debug)]
pub enum KubernetesError {
/// Kubernetes API client error
#[error("Kubernetes API error: {0}")]
ApiError(#[from] kube::Error),
/// Configuration error
#[error("Configuration error: {0}")]
ConfigError(String),
/// Resource not found error
#[error("Resource not found: {0}")]
ResourceNotFound(String),
/// Invalid resource name or pattern
#[error("Invalid resource name or pattern: {0}")]
InvalidResourceName(String),
/// Regular expression error
#[error("Regular expression error: {0}")]
RegexError(#[from] regex::Error),
/// Serialization/deserialization error
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
/// YAML parsing error
#[error("YAML error: {0}")]
YamlError(#[from] serde_yaml::Error),
/// Generic operation error
#[error("Operation failed: {0}")]
OperationError(String),
/// Namespace error
#[error("Namespace error: {0}")]
NamespaceError(String),
/// Permission denied error
#[error("Permission denied: {0}")]
PermissionDenied(String),
/// Timeout error
#[error("Operation timed out: {0}")]
Timeout(String),
/// Generic error wrapper
#[error("Generic error: {0}")]
Generic(#[from] anyhow::Error),
}
impl KubernetesError {
/// Create a new configuration error
pub fn config_error(msg: impl Into<String>) -> Self {
Self::ConfigError(msg.into())
}
/// Create a new operation error
pub fn operation_error(msg: impl Into<String>) -> Self {
Self::OperationError(msg.into())
}
/// Create a new namespace error
pub fn namespace_error(msg: impl Into<String>) -> Self {
Self::NamespaceError(msg.into())
}
/// Create a new permission denied error
pub fn permission_denied(msg: impl Into<String>) -> Self {
Self::PermissionDenied(msg.into())
}
/// Create a new timeout error
pub fn timeout(msg: impl Into<String>) -> Self {
Self::Timeout(msg.into())
}
}
/// Result type for Kubernetes operations
pub type KubernetesResult<T> = Result<T, KubernetesError>;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
//! SAL Kubernetes: Kubernetes cluster management and operations
//!
//! This package provides Kubernetes cluster management functionality including:
//! - Namespace-scoped resource management via KubernetesManager
//! - Pod listing and management
//! - Resource deletion with PCRE pattern matching
//! - Namespace creation and management
//! - Support for various Kubernetes resources (pods, services, deployments, etc.)
//!
//! # Example
//!
//! ```rust
//! use sal_kubernetes::KubernetesManager;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Create a manager for the "default" namespace
//! let km = KubernetesManager::new("default").await?;
//!
//! // List all pods in the namespace
//! let pods = km.pods_list().await?;
//! println!("Found {} pods", pods.len());
//!
//! // Create a namespace (idempotent)
//! km.namespace_create("my-namespace").await?;
//!
//! // Delete resources matching a pattern
//! km.delete("test-.*").await?;
//!
//! Ok(())
//! }
//! ```
pub mod config;
pub mod error;
pub mod kubernetes_manager;
// Rhai integration module
#[cfg(feature = "rhai")]
pub mod rhai;
// Re-export main types for convenience
pub use config::KubernetesConfig;
pub use error::KubernetesError;
pub use kubernetes_manager::KubernetesManager;
// Re-export commonly used Kubernetes types
pub use k8s_openapi::api::apps::v1::{Deployment, ReplicaSet};
pub use k8s_openapi::api::core::v1::{Namespace, Pod, Service};

View File

@@ -0,0 +1,729 @@
//! Rhai wrappers for Kubernetes module functions
//!
//! This module provides Rhai wrappers for the functions in the Kubernetes module,
//! enabling scripting access to Kubernetes operations.
use crate::{KubernetesError, KubernetesManager};
use once_cell::sync::Lazy;
use rhai::{Array, Dynamic, Engine, EvalAltResult, Map};
use std::sync::Mutex;
use tokio::runtime::Runtime;
// Global Tokio runtime for blocking async operations
static RUNTIME: Lazy<Mutex<Runtime>> =
Lazy::new(|| Mutex::new(Runtime::new().expect("Failed to create Tokio runtime")));
/// Helper function to convert Rhai Map to HashMap for environment variables
///
/// # Arguments
///
/// * `rhai_map` - Rhai Map containing key-value pairs
///
/// # Returns
///
/// * `Option<std::collections::HashMap<String, String>>` - Converted HashMap or None if empty
fn convert_rhai_map_to_env_vars(
rhai_map: Map,
) -> Option<std::collections::HashMap<String, String>> {
if rhai_map.is_empty() {
None
} else {
Some(
rhai_map
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
)
}
}
/// Helper function to execute async operations with proper runtime handling
///
/// This uses a global runtime to ensure consistent async execution
fn execute_async<F, T>(future: F) -> Result<T, Box<EvalAltResult>>
where
F: std::future::Future<Output = Result<T, KubernetesError>>,
{
// Get the global runtime
let rt = match RUNTIME.lock() {
Ok(rt) => rt,
Err(e) => {
return Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to acquire runtime lock: {e}").into(),
rhai::Position::NONE,
)));
}
};
// Execute the future in a blocking manner
rt.block_on(future).map_err(kubernetes_error_to_rhai_error)
}
/// Create a new KubernetesManager for the specified namespace
///
/// # Arguments
///
/// * `namespace` - The Kubernetes namespace to operate on
///
/// # Returns
///
/// * `Result<KubernetesManager, Box<EvalAltResult>>` - The manager instance or an error
fn kubernetes_manager_new(namespace: String) -> Result<KubernetesManager, Box<EvalAltResult>> {
execute_async(KubernetesManager::new(namespace))
}
/// List all pods in the namespace
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `Result<Array, Box<EvalAltResult>>` - Array of pod names or an error
fn pods_list(km: &mut KubernetesManager) -> Result<Array, Box<EvalAltResult>> {
let pods = execute_async(km.pods_list())?;
let pod_names: Array = pods
.iter()
.filter_map(|pod| pod.metadata.name.as_ref())
.map(|name| Dynamic::from(name.clone()))
.collect();
Ok(pod_names)
}
/// List all services in the namespace
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `Result<Array, Box<EvalAltResult>>` - Array of service names or an error
fn services_list(km: &mut KubernetesManager) -> Result<Array, Box<EvalAltResult>> {
let services = execute_async(km.services_list())?;
let service_names: Array = services
.iter()
.filter_map(|service| service.metadata.name.as_ref())
.map(|name| Dynamic::from(name.clone()))
.collect();
Ok(service_names)
}
/// List all deployments in the namespace
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `Result<Array, Box<EvalAltResult>>` - Array of deployment names or an error
fn deployments_list(km: &mut KubernetesManager) -> Result<Array, Box<EvalAltResult>> {
let deployments = execute_async(km.deployments_list())?;
let deployment_names: Array = deployments
.iter()
.filter_map(|deployment| deployment.metadata.name.as_ref())
.map(|name| Dynamic::from(name.clone()))
.collect();
Ok(deployment_names)
}
/// List all configmaps in the namespace
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `Result<Array, Box<EvalAltResult>>` - Array of configmap names or an error
fn configmaps_list(km: &mut KubernetesManager) -> Result<Array, Box<EvalAltResult>> {
let configmaps = execute_async(km.configmaps_list())?;
let configmap_names: Array = configmaps
.iter()
.filter_map(|configmap| configmap.metadata.name.as_ref())
.map(|name| Dynamic::from(name.clone()))
.collect();
Ok(configmap_names)
}
/// List all secrets in the namespace
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `Result<Array, Box<EvalAltResult>>` - Array of secret names or an error
fn secrets_list(km: &mut KubernetesManager) -> Result<Array, Box<EvalAltResult>> {
let secrets = execute_async(km.secrets_list())?;
let secret_names: Array = secrets
.iter()
.filter_map(|secret| secret.metadata.name.as_ref())
.map(|name| Dynamic::from(name.clone()))
.collect();
Ok(secret_names)
}
/// Delete resources matching a PCRE pattern
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
/// * `pattern` - PCRE pattern to match resource names against
///
/// # Returns
///
/// * `Result<i64, Box<EvalAltResult>>` - Number of resources deleted or an error
///
/// Create a pod with a single container (backward compatible version)
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the pod
/// * `image` - Container image to use
/// * `labels` - Optional labels as a Map
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Pod name or an error
fn pod_create(
km: &mut KubernetesManager,
name: String,
image: String,
labels: Map,
) -> Result<String, Box<EvalAltResult>> {
let labels_map: Option<std::collections::HashMap<String, String>> = if labels.is_empty() {
None
} else {
Some(
labels
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
)
};
let pod = execute_async(km.pod_create(&name, &image, labels_map, None))?;
Ok(pod.metadata.name.unwrap_or(name))
}
/// Create a pod with a single container and environment variables
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the pod
/// * `image` - Container image to use
/// * `labels` - Optional labels as a Map
/// * `env_vars` - Optional environment variables as a Map
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Pod name or an error
fn pod_create_with_env(
km: &mut KubernetesManager,
name: String,
image: String,
labels: Map,
env_vars: Map,
) -> Result<String, Box<EvalAltResult>> {
let labels_map: Option<std::collections::HashMap<String, String>> = if labels.is_empty() {
None
} else {
Some(
labels
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
)
};
let env_vars_map = convert_rhai_map_to_env_vars(env_vars);
let pod = execute_async(km.pod_create(&name, &image, labels_map, env_vars_map))?;
Ok(pod.metadata.name.unwrap_or(name))
}
/// Create a service
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the service
/// * `selector` - Labels to select pods as a Map
/// * `port` - Port to expose
/// * `target_port` - Target port on pods (optional, defaults to port)
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Service name or an error
fn service_create(
km: &mut KubernetesManager,
name: String,
selector: Map,
port: i64,
target_port: i64,
) -> Result<String, Box<EvalAltResult>> {
let selector_map: std::collections::HashMap<String, String> = selector
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect();
let target_port_opt = if target_port == 0 {
None
} else {
Some(target_port as i32)
};
let service =
execute_async(km.service_create(&name, selector_map, port as i32, target_port_opt))?;
Ok(service.metadata.name.unwrap_or(name))
}
/// Create a deployment
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the deployment
/// * `image` - Container image to use
/// * `replicas` - Number of replicas
/// * `labels` - Optional labels as a Map
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Deployment name or an error
fn deployment_create(
km: &mut KubernetesManager,
name: String,
image: String,
replicas: i64,
labels: Map,
env_vars: Map,
) -> Result<String, Box<EvalAltResult>> {
let labels_map: Option<std::collections::HashMap<String, String>> = if labels.is_empty() {
None
} else {
Some(
labels
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
)
};
let env_vars_map = convert_rhai_map_to_env_vars(env_vars);
let deployment = execute_async(km.deployment_create(
&name,
&image,
replicas as i32,
labels_map,
env_vars_map,
))?;
Ok(deployment.metadata.name.unwrap_or(name))
}
/// Create a ConfigMap
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the ConfigMap
/// * `data` - Data as a Map
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - ConfigMap name or an error
fn configmap_create(
km: &mut KubernetesManager,
name: String,
data: Map,
) -> Result<String, Box<EvalAltResult>> {
let data_map: std::collections::HashMap<String, String> = data
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect();
let configmap = execute_async(km.configmap_create(&name, data_map))?;
Ok(configmap.metadata.name.unwrap_or(name))
}
/// Create a Secret
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the Secret
/// * `data` - Data as a Map (will be base64 encoded)
/// * `secret_type` - Type of secret (optional, defaults to "Opaque")
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Secret name or an error
fn secret_create(
km: &mut KubernetesManager,
name: String,
data: Map,
secret_type: String,
) -> Result<String, Box<EvalAltResult>> {
let data_map: std::collections::HashMap<String, String> = data
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect();
let secret_type_opt = if secret_type.is_empty() {
None
} else {
Some(secret_type.as_str())
};
let secret = execute_async(km.secret_create(&name, data_map, secret_type_opt))?;
Ok(secret.metadata.name.unwrap_or(name))
}
/// Get a pod by name
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the pod to get
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Pod name or an error
fn pod_get(km: &mut KubernetesManager, name: String) -> Result<String, Box<EvalAltResult>> {
let pod = execute_async(km.pod_get(&name))?;
Ok(pod.metadata.name.unwrap_or(name))
}
/// Get a service by name
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the service to get
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Service name or an error
fn service_get(km: &mut KubernetesManager, name: String) -> Result<String, Box<EvalAltResult>> {
let service = execute_async(km.service_get(&name))?;
Ok(service.metadata.name.unwrap_or(name))
}
/// Get a deployment by name
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the deployment to get
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Deployment name or an error
fn deployment_get(km: &mut KubernetesManager, name: String) -> Result<String, Box<EvalAltResult>> {
let deployment = execute_async(km.deployment_get(&name))?;
Ok(deployment.metadata.name.unwrap_or(name))
}
fn delete(km: &mut KubernetesManager, pattern: String) -> Result<i64, Box<EvalAltResult>> {
let deleted_count = execute_async(km.delete(&pattern))?;
Ok(deleted_count as i64)
}
/// Create a namespace (idempotent operation)
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
/// * `name` - The name of the namespace to create
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Success or an error
fn namespace_create(km: &mut KubernetesManager, name: String) -> Result<(), Box<EvalAltResult>> {
execute_async(km.namespace_create(&name))
}
/// Delete a namespace (destructive operation)
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the namespace to delete
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Success or an error
fn namespace_delete(km: &mut KubernetesManager, name: String) -> Result<(), Box<EvalAltResult>> {
execute_async(km.namespace_delete(&name))
}
/// Check if a namespace exists
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
/// * `name` - The name of the namespace to check
///
/// # Returns
///
/// * `Result<bool, Box<EvalAltResult>>` - True if namespace exists, false otherwise
fn namespace_exists(km: &mut KubernetesManager, name: String) -> Result<bool, Box<EvalAltResult>> {
execute_async(km.namespace_exists(&name))
}
/// List all namespaces
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `Result<Array, Box<EvalAltResult>>` - Array of namespace names or an error
fn namespaces_list(km: &mut KubernetesManager) -> Result<Array, Box<EvalAltResult>> {
let namespaces = execute_async(km.namespaces_list())?;
let namespace_names: Array = namespaces
.iter()
.filter_map(|ns| ns.metadata.name.as_ref())
.map(|name| Dynamic::from(name.clone()))
.collect();
Ok(namespace_names)
}
/// Get resource counts for the namespace
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `Result<Map, Box<EvalAltResult>>` - Map of resource counts by type or an error
fn resource_counts(km: &mut KubernetesManager) -> Result<Map, Box<EvalAltResult>> {
let counts = execute_async(km.resource_counts())?;
let mut rhai_map = Map::new();
for (key, value) in counts {
rhai_map.insert(key.into(), Dynamic::from(value as i64));
}
Ok(rhai_map)
}
/// Deploy a complete application with deployment and service
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the application
/// * `image` - Container image to use
/// * `replicas` - Number of replicas
/// * `port` - Port the application listens on
/// * `labels` - Optional labels as a Map
/// * `env_vars` - Optional environment variables as a Map
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - Success message or an error
fn deploy_application(
km: &mut KubernetesManager,
name: String,
image: String,
replicas: i64,
port: i64,
labels: Map,
env_vars: Map,
) -> Result<String, Box<EvalAltResult>> {
let labels_map: Option<std::collections::HashMap<String, String>> = if labels.is_empty() {
None
} else {
Some(
labels
.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
)
};
let env_vars_map = convert_rhai_map_to_env_vars(env_vars);
execute_async(km.deploy_application(
&name,
&image,
replicas as i32,
port as i32,
labels_map,
env_vars_map,
))?;
Ok(format!("Successfully deployed application '{name}'"))
}
/// Delete a specific pod by name
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
/// * `name` - The name of the pod to delete
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Success or an error
fn pod_delete(km: &mut KubernetesManager, name: String) -> Result<(), Box<EvalAltResult>> {
execute_async(km.pod_delete(&name))
}
/// Delete a specific service by name
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
/// * `name` - The name of the service to delete
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Success or an error
fn service_delete(km: &mut KubernetesManager, name: String) -> Result<(), Box<EvalAltResult>> {
execute_async(km.service_delete(&name))
}
/// Delete a specific deployment by name
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
/// * `name` - The name of the deployment to delete
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Success or an error
fn deployment_delete(km: &mut KubernetesManager, name: String) -> Result<(), Box<EvalAltResult>> {
execute_async(km.deployment_delete(&name))
}
/// Delete a ConfigMap by name
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the ConfigMap to delete
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Success or an error
fn configmap_delete(km: &mut KubernetesManager, name: String) -> Result<(), Box<EvalAltResult>> {
execute_async(km.configmap_delete(&name))
}
/// Delete a Secret by name
///
/// # Arguments
///
/// * `km` - Mutable reference to KubernetesManager
/// * `name` - Name of the Secret to delete
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Success or an error
fn secret_delete(km: &mut KubernetesManager, name: String) -> Result<(), Box<EvalAltResult>> {
execute_async(km.secret_delete(&name))
}
/// Get the namespace this manager operates on
///
/// # Arguments
///
/// * `km` - The KubernetesManager instance
///
/// # Returns
///
/// * `String` - The namespace name
fn kubernetes_manager_namespace(km: &mut KubernetesManager) -> String {
km.namespace().to_string()
}
/// Register Kubernetes module functions with the Rhai engine
///
/// # Arguments
///
/// * `engine` - The Rhai engine to register the functions with
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
pub fn register_kubernetes_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
// Register KubernetesManager type
engine.register_type::<KubernetesManager>();
// Register KubernetesManager constructor and methods
engine.register_fn("kubernetes_manager_new", kubernetes_manager_new);
engine.register_fn("namespace", kubernetes_manager_namespace);
// Register resource listing functions
engine.register_fn("pods_list", pods_list);
engine.register_fn("services_list", services_list);
engine.register_fn("deployments_list", deployments_list);
engine.register_fn("configmaps_list", configmaps_list);
engine.register_fn("secrets_list", secrets_list);
engine.register_fn("namespaces_list", namespaces_list);
// Register resource creation methods (object-oriented style)
engine.register_fn("create_pod", pod_create);
engine.register_fn("create_pod_with_env", pod_create_with_env);
engine.register_fn("create_service", service_create);
engine.register_fn("create_deployment", deployment_create);
engine.register_fn("create_configmap", configmap_create);
engine.register_fn("create_secret", secret_create);
// Register resource get methods
engine.register_fn("get_pod", pod_get);
engine.register_fn("get_service", service_get);
engine.register_fn("get_deployment", deployment_get);
// Register resource management methods
engine.register_fn("delete", delete);
engine.register_fn("delete_pod", pod_delete);
engine.register_fn("delete_service", service_delete);
engine.register_fn("delete_deployment", deployment_delete);
engine.register_fn("delete_configmap", configmap_delete);
engine.register_fn("delete_secret", secret_delete);
// Register namespace methods (object-oriented style)
engine.register_fn("create_namespace", namespace_create);
engine.register_fn("delete_namespace", namespace_delete);
engine.register_fn("namespace_exists", namespace_exists);
// Register utility functions
engine.register_fn("resource_counts", resource_counts);
// Register convenience functions
engine.register_fn("deploy_application", deploy_application);
Ok(())
}
// Helper function for error conversion
fn kubernetes_error_to_rhai_error(error: KubernetesError) -> Box<EvalAltResult> {
Box::new(EvalAltResult::ErrorRuntime(
format!("Kubernetes error: {error}").into(),
rhai::Position::NONE,
))
}