diff --git a/core/Cargo.toml b/core/Cargo.toml index 1bcd3e51..80875fd4 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -4,7 +4,6 @@ resolver = "2" members = [ "archipelago", "container", - "parmanode", "performance", "security", ] diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index 817738b9..0965cdce 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -34,7 +34,7 @@ futures-util = "0.3" archipelago-container = { path = "../container" } archipelago-security = { path = "../security" } archipelago-performance = { path = "../performance" } -archipelago-parmanode = { path = "../parmanode" } + # Database (optional for now - can use SQLite or skip) # sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio-rustls"] } diff --git a/core/parmanode/Cargo.toml b/core/parmanode/Cargo.toml deleted file mode 100644 index 62358efc..00000000 --- a/core/parmanode/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "archipelago-parmanode" -version = "0.1.0" -edition = "2021" - -[dependencies] -tokio = { version = "1", features = ["full"] } -serde = { version = "1.0", features = ["derive"] } -serde_yaml = "0.9" -anyhow = "1.0" -thiserror = "1.0" -archipelago-container = { path = "../container" } -log = "0.4" -tracing = "0.1" - -[lib] -name = "archipelago_parmanode" -path = "src/lib.rs" diff --git a/core/parmanode/src/converter.rs b/core/parmanode/src/converter.rs deleted file mode 100644 index b12aee35..00000000 --- a/core/parmanode/src/converter.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Parmanode to App Manifest converter -// Converts Parmanode module structure to Archipelago app manifest format - -use archipelago_container::AppManifest; -use anyhow::{Context, Result}; -use std::path::PathBuf; -use tokio::fs; -use tracing::info; - -pub struct ParmanodeConverter; - -impl ParmanodeConverter { - pub fn new() -> Self { - Self - } - - /// Convert a Parmanode module directory to an App Manifest - pub async fn convert_to_manifest(&self, module_path: &PathBuf) -> Result { - info!("Converting Parmanode module to manifest: {:?}", module_path); - - // Read Parmanode module metadata if available - let module_name = module_path - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or("unknown") - .to_string(); - - // Try to detect what the module installs - let install_script = module_path.join("install.sh"); - let script_content = if install_script.exists() { - fs::read_to_string(&install_script).await.ok() - } else { - None - }; - - // Infer app details from script content - let (app_id, image) = self.infer_from_script(&script_content)?; - - // Create a basic manifest - let manifest_yaml = format!( - r#" -app: - id: {} - name: {} - version: 1.0.0 - description: Converted from Parmanode module - - container: - image: {} - pull_policy: if-not-present - - resources: - cpu_limit: 1 - memory_limit: 512Mi - disk_limit: 10Gi - - security: - capabilities: [] - readonly_root: true - network_policy: isolated -"#, - app_id, module_name, image - ); - - AppManifest::from_str(&manifest_yaml) - .context("Failed to create manifest from Parmanode module") - } - - fn infer_from_script(&self, script_content: &Option) -> Result<(String, String)> { - let content = script_content.as_deref().unwrap_or(""); - - // Try to detect Bitcoin Core - if content.contains("bitcoind") || content.contains("bitcoin-core") { - return Ok(("bitcoin-core".to_string(), "bitcoin/bitcoin:24.0".to_string())); - } - - // Try to detect LND - if content.contains("lnd") && !content.contains("lightning") { - return Ok(("lnd".to_string(), "lightninglabs/lnd:v0.18.0".to_string())); - } - - // Try to detect Core Lightning - if content.contains("clightning") || content.contains("core-lightning") { - return Ok(("core-lightning".to_string(), "elementsproject/lightningd:v23.08.2".to_string())); - } - - // Try to detect Electrs - if content.contains("electrs") { - return Ok(("electrs".to_string(), "romanz/electrs:v0.10.0".to_string())); - } - - // Default fallback — pin Alpine to a specific version - Ok(("parmanode-module".to_string(), "alpine:3.19".to_string())) - } -} - -impl Default for ParmanodeConverter { - fn default() -> Self { - Self::new() - } -} diff --git a/core/parmanode/src/lib.rs b/core/parmanode/src/lib.rs deleted file mode 100644 index b6c30b55..00000000 --- a/core/parmanode/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod script_runner; -pub mod converter; - -pub use script_runner::ParmanodeScriptRunner; -pub use converter::ParmanodeConverter; diff --git a/core/parmanode/src/script_runner.rs b/core/parmanode/src/script_runner.rs deleted file mode 100644 index 5f869cb0..00000000 --- a/core/parmanode/src/script_runner.rs +++ /dev/null @@ -1,128 +0,0 @@ -// Parmanode script runner - executes Parmanode installation scripts in containers -// Provides compatibility layer for existing Parmanode modules - -use archipelago_container::PodmanClient; -use anyhow::{Context, Result}; -use std::path::PathBuf; -use std::process::Command; -use tokio::fs; -use tracing::{info, warn}; - -pub struct ParmanodeScriptRunner { - _podman: PodmanClient, - _scripts_dir: PathBuf, -} - -impl ParmanodeScriptRunner { - pub fn new(scripts_dir: PathBuf) -> Self { - Self { - _podman: PodmanClient::new("archipelago".to_string()), - _scripts_dir: scripts_dir, - } - } - - /// Detect if a path contains a Parmanode script - pub fn is_parmanode_script(&self, path: &PathBuf) -> bool { - // Check for common Parmanode script patterns - path.file_name() - .and_then(|name| name.to_str()) - .map(|name| { - name.ends_with(".sh") && ( - name.contains("parmanode") || - name.contains("bitcoin") || - name.contains("lightning") || - name.contains("electrs") - ) - }) - .unwrap_or(false) - } - - /// Run a Parmanode script in an isolated container - pub async fn run_script(&self, script_path: &PathBuf) -> Result<()> { - info!("Running Parmanode script: {:?}", script_path); - - // Create a temporary container manifest for the script - let script_name = script_path - .file_stem() - .and_then(|s| s.to_str()) - .unwrap_or("parmanode-script"); - - // Create a minimal container to run the script - let _container_name = format!("parmanode-{}", script_name); - - // Copy script to a location accessible by containers - let script_content = fs::read_to_string(script_path).await - .context("Failed to read Parmanode script")?; - - // Create a wrapper script that runs in Alpine - let wrapper_script = format!( - r#"#!/bin/sh -set -e -{} -"#, - script_content - ); - - // Write wrapper to temp location - let temp_script = format!("/tmp/parmanode-{}.sh", script_name); - fs::write(&temp_script, wrapper_script).await - .context("Failed to write wrapper script")?; - - // Make executable - Command::new("chmod") - .arg("+x") - .arg(&temp_script) - .output() - .context("Failed to make script executable")?; - - // Run script in a temporary Alpine container - let output = Command::new("podman") - .arg("run") - .arg("--rm") - .arg("--volume") - .arg(format!("{}:/script.sh:ro", temp_script)) - .arg("alpine:latest") - .arg("sh") - .arg("/script.sh") - .output() - .context("Failed to execute Parmanode script in container")?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr); - return Err(anyhow::anyhow!("Parmanode script failed: {}", stderr)); - } - - info!("Parmanode script completed successfully"); - Ok(()) - } - - /// Install a Parmanode module (runs script and sets up container) - pub async fn install_module(&self, module_path: &PathBuf) -> Result { - // Find the main installation script - let install_script = module_path.join("install.sh"); - if !install_script.exists() { - return Err(anyhow::anyhow!("No install.sh found in Parmanode module")); - } - - // Run the installation script - self.run_script(&install_script).await?; - - // Try to convert to app manifest for future management - let converter = crate::converter::ParmanodeConverter::new(); - match converter.convert_to_manifest(module_path).await { - Ok(manifest) => { - info!("Converted Parmanode module to app manifest"); - // TODO: Save manifest for future use - Ok(manifest.app.id) - } - Err(e) => { - warn!("Failed to convert Parmanode module: {}", e); - // Return a generic ID - Ok(format!("parmanode-{}", - module_path.file_name() - .and_then(|n| n.to_str()) - .unwrap_or("module"))) - } - } - } -}