Enhance development workflow and deployment practices for Archipelago
- Updated the Development-Workflow documentation to clarify deployment strategy, emphasizing direct deployment to the live system for testing. - Added detailed instructions for the deployment command, including syncing code, building frontend and backend, and restarting services. - Improved SSH key management section to assist with authentication issues. - Expanded the testing workflow to include steps for checking logs and syncing changes back to the ISO build. - Updated the ISO build integration section to ensure system-level changes are captured for future builds. - Refactored various sections for clarity and completeness, including deployment paths and system configuration files.
This commit is contained in:
@@ -55,9 +55,13 @@ pub struct PodmanClient {
|
||||
|
||||
impl PodmanClient {
|
||||
pub fn new(user: String) -> Self {
|
||||
// If running as root, use root podman context
|
||||
let is_root = std::env::var("USER").unwrap_or_default() == "root" ||
|
||||
std::env::var("HOME").unwrap_or_default() == "/root";
|
||||
|
||||
Self {
|
||||
_user: user,
|
||||
rootless: true,
|
||||
rootless: !is_root,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,25 +319,101 @@ impl PodmanClient {
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
log::error!("Podman list failed: {}", stderr);
|
||||
return Err(anyhow::anyhow!("Failed to list containers: {}", stderr));
|
||||
}
|
||||
|
||||
let json = String::from_utf8_lossy(&output.stdout);
|
||||
let containers: Vec<serde_json::Value> = serde_json::from_str(&json)
|
||||
.context("Failed to parse container list")?;
|
||||
log::debug!("Podman JSON output ({} bytes): {}", json.len(),
|
||||
if json.len() > 200 { &json[..200] } else { &json });
|
||||
|
||||
// Podman can return either a JSON array or NDJSON (newline-delimited JSON)
|
||||
let mut result = Vec::new();
|
||||
for container in containers {
|
||||
result.push(ContainerStatus {
|
||||
id: container["Id"].as_str().unwrap_or("").to_string(),
|
||||
name: container["Names"][0].as_str().unwrap_or("").to_string(),
|
||||
state: ContainerState::from(container["State"].as_str().unwrap_or("unknown")),
|
||||
image: container["Image"].as_str().unwrap_or("").to_string(),
|
||||
created: container["Created"].as_str().unwrap_or("").to_string(),
|
||||
ports: vec![],
|
||||
});
|
||||
|
||||
// Try parsing as a JSON array first
|
||||
if let Ok(containers) = serde_json::from_str::<Vec<serde_json::Value>>(&json) {
|
||||
log::debug!("Parsed as JSON array with {} items", containers.len());
|
||||
for container in containers {
|
||||
// Handle both Names as array and Names as string
|
||||
let name = if let Some(names_array) = container["Names"].as_array() {
|
||||
names_array.get(0).and_then(|v| v.as_str()).unwrap_or("").to_string()
|
||||
} else {
|
||||
container["Names"].as_str().unwrap_or("").to_string()
|
||||
};
|
||||
|
||||
// Parse ports from the Ports array
|
||||
let ports = if let Some(ports_array) = container["Ports"].as_array() {
|
||||
ports_array.iter().filter_map(|port| {
|
||||
// Podman format: {"host_ip":"","container_port":8123,"host_port":8123,"range":1,"protocol":"tcp"}
|
||||
if let (Some(host_port), Some(container_port), Some(protocol)) = (
|
||||
port["host_port"].as_u64(),
|
||||
port["container_port"].as_u64(),
|
||||
port["protocol"].as_str()
|
||||
) {
|
||||
Some(format!("0.0.0.0:{}->{}/{}", host_port, container_port, protocol))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
result.push(ContainerStatus {
|
||||
id: container["Id"].as_str().unwrap_or("").to_string(),
|
||||
name,
|
||||
state: ContainerState::from(container["State"].as_str().unwrap_or("unknown")),
|
||||
image: container["Image"].as_str().unwrap_or("").to_string(),
|
||||
created: container["Created"].as_str().unwrap_or("").to_string(),
|
||||
ports,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
log::debug!("Failed to parse as JSON array, trying NDJSON");
|
||||
// Try parsing as NDJSON (newline-delimited JSON)
|
||||
for line in json.lines() {
|
||||
if line.trim().is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(container) = serde_json::from_str::<serde_json::Value>(line) {
|
||||
// Handle both Names as array and Names as string
|
||||
let name = if let Some(names_array) = container["Names"].as_array() {
|
||||
names_array.get(0).and_then(|v| v.as_str()).unwrap_or("").to_string()
|
||||
} else {
|
||||
container["Names"].as_str().unwrap_or("").to_string()
|
||||
};
|
||||
|
||||
// Parse ports from the Ports array
|
||||
let ports = if let Some(ports_array) = container["Ports"].as_array() {
|
||||
ports_array.iter().filter_map(|port| {
|
||||
if let (Some(host_port), Some(container_port), Some(protocol)) = (
|
||||
port["host_port"].as_u64(),
|
||||
port["container_port"].as_u64(),
|
||||
port["protocol"].as_str()
|
||||
) {
|
||||
Some(format!("0.0.0.0:{}->{}/{}", host_port, container_port, protocol))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
result.push(ContainerStatus {
|
||||
id: container["Id"].as_str().unwrap_or("").to_string(),
|
||||
name,
|
||||
state: ContainerState::from(container["State"].as_str().unwrap_or("unknown")),
|
||||
image: container["Image"].as_str().unwrap_or("").to_string(),
|
||||
created: container["Created"].as_str().unwrap_or("").to_string(),
|
||||
ports,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("Returning {} containers", result.len());
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user