forked from NationTech/harmony
fix(k8s_anywhere): Ensure k3d cluster is started before use
- Refactor k3d cluster management to explicitly start the cluster. - Introduce `start_cluster` function to ensure cluster is running before operations. - Improve error handling and logging during cluster startup. - Update `create_cluster` and other related functions to utilize the new startup mechanism. - Enhance reliability and prevent potential issues caused by an uninitialized cluster. - Add `run_k3d_command` to handle k3d commands with logging and error handling.
This commit is contained in:
@@ -117,7 +117,7 @@ impl K3d {
|
||||
/// 2. It has proper executable permissions (on Unix systems)
|
||||
/// 3. It responds correctly to a simple command (`k3d --version`)
|
||||
pub fn is_installed(&self) -> bool {
|
||||
let binary_path = self.base_dir.join(K3D_BIN_FILE_NAME);
|
||||
let binary_path = self.get_k3d_binary_path();
|
||||
|
||||
if !binary_path.exists() {
|
||||
debug!("K3d binary not found at {:?}", binary_path);
|
||||
@@ -131,15 +131,15 @@ impl K3d {
|
||||
self.can_execute_binary_check(&binary_path)
|
||||
}
|
||||
|
||||
/// Verifies if the specified cluster is already running
|
||||
/// Verifies if the specified cluster is already created
|
||||
///
|
||||
/// Executes `k3d cluster list <cluster_name>` and checks for a successful response,
|
||||
/// indicating that the cluster exists and is registered with k3d.
|
||||
pub fn is_cluster_initialized(&self) -> bool {
|
||||
let cluster_name = match &self.cluster_name {
|
||||
Some(name) => name,
|
||||
None => {
|
||||
debug!("No cluster name specified, can't verify if cluster is initialized");
|
||||
let cluster_name = match self.get_cluster_name() {
|
||||
Ok(name) => name,
|
||||
Err(_) => {
|
||||
debug!("Could not get cluster name, can't verify if cluster is initialized");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -152,6 +152,13 @@ impl K3d {
|
||||
self.verify_cluster_exists(&binary_path, cluster_name)
|
||||
}
|
||||
|
||||
fn get_cluster_name(&self) -> Result<&String, String> {
|
||||
match &self.cluster_name {
|
||||
Some(name) => Ok(name),
|
||||
None => Err("No cluster name available".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new k3d cluster with the specified name
|
||||
///
|
||||
/// This method:
|
||||
@@ -163,22 +170,29 @@ impl K3d {
|
||||
/// - `Ok(Client)` - Successfully created cluster and connected client
|
||||
/// - `Err(String)` - Error message detailing what went wrong
|
||||
pub async fn initialize_cluster(&self) -> Result<Client, String> {
|
||||
let cluster_name = match &self.cluster_name {
|
||||
Some(name) => name,
|
||||
None => return Err("No cluster name specified for initialization".to_string()),
|
||||
let cluster_name = match self.get_cluster_name() {
|
||||
Ok(name) => name,
|
||||
Err(_) => return Err("Could not get cluster_name, cannot initialize".to_string()),
|
||||
};
|
||||
|
||||
let binary_path = self.base_dir.join(K3D_BIN_FILE_NAME);
|
||||
if !binary_path.exists() {
|
||||
return Err(format!("K3d binary not found at {:?}", binary_path));
|
||||
}
|
||||
|
||||
info!("Initializing k3d cluster '{}'", cluster_name);
|
||||
|
||||
self.create_cluster(&binary_path, cluster_name)?;
|
||||
self.create_cluster(cluster_name)?;
|
||||
self.create_kubernetes_client().await
|
||||
}
|
||||
|
||||
fn get_k3d_binary_path(&self) -> PathBuf {
|
||||
self.base_dir.join(K3D_BIN_FILE_NAME)
|
||||
}
|
||||
|
||||
fn get_k3d_binary(&self) -> Result<PathBuf, String> {
|
||||
let path = self.get_k3d_binary_path();
|
||||
if !path.exists() {
|
||||
return Err(format!("K3d binary not found at {:?}", path));
|
||||
}
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// Ensures k3d is installed and the cluster is initialized
|
||||
///
|
||||
/// This method provides a complete setup flow:
|
||||
@@ -206,6 +220,8 @@ impl K3d {
|
||||
return self.initialize_cluster().await;
|
||||
}
|
||||
|
||||
self.start_cluster().await?;
|
||||
|
||||
info!("K3d and cluster are already properly set up");
|
||||
self.create_kubernetes_client().await
|
||||
}
|
||||
@@ -282,11 +298,27 @@ impl K3d {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_cluster(&self, binary_path: &PathBuf, cluster_name: &str) -> Result<(), String> {
|
||||
let output = std::process::Command::new(binary_path)
|
||||
.args(["cluster", "create", cluster_name])
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to execute k3d command: {}", e))?;
|
||||
pub fn run_k3d_command<I, S>(&self, args: I) -> Result<std::process::Output, String>
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<std::ffi::OsStr>,
|
||||
{
|
||||
let binary_path = self.get_k3d_binary()?;
|
||||
let output = std::process::Command::new(binary_path).args(args).output();
|
||||
match output {
|
||||
Ok(output) => {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
debug!("stderr : {}", stderr);
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
debug!("stdout : {}", stdout);
|
||||
Ok(output)
|
||||
}
|
||||
Err(e) => Err(format!("Failed to execute k3d command: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_cluster(&self, cluster_name: &str) -> Result<(), String> {
|
||||
let output = self.run_k3d_command(["cluster", "create", cluster_name])?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
@@ -310,6 +342,19 @@ impl K3d {
|
||||
false => Err("Cannot get client! Cluster not initialized yet".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_cluster(&self) -> Result<(), String> {
|
||||
let cluster_name = self.get_cluster_name()?;
|
||||
let output = self.run_k3d_command(["cluster", "start", cluster_name])?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(format!("Failed to start cluster: {}", stderr));
|
||||
}
|
||||
|
||||
info!("Successfully started k3d cluster '{}'", cluster_name);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user