This commit is contained in:
kristof 2025-06-16 07:30:37 +02:00
parent 49c879359b
commit dee38eb6c2
9 changed files with 270 additions and 5 deletions

View File

@ -49,13 +49,17 @@ sha2 = "0.10.7" # SHA-2 hash functions
tempfile = "3.5" # For temporary file operations
tera = "1.19.0" # Template engine for text rendering
thiserror = "2.0.12" # For error handling
tokio = "1.45.0"
tokio = { version = "1.45.0", features = ["full"] }
tokio-postgres = "0.7.8" # Async PostgreSQL client
tokio-test = "0.4.4"
uuid = { version = "1.16.0", features = ["v4"] }
reqwest = { version = "0.12.15", features = ["json"] }
urlencoding = "2.1.3"
zinit-client = "0.3.0"
russh = "0.42.0"
russh-keys = "0.42.0"
async-trait = "0.1.81"
futures = "0.3.30"
# Optional features for specific OS functionality
[target.'cfg(unix)'.dependencies]

View File

@ -9,7 +9,7 @@ println(`Using local image: ${local_image_name}`);
// Import the image from buildah to nerdctl
println("Importing image from buildah to nerdctl...");
process_run("buildah", ["push", "custom-golang-nginx:latest", "docker-daemon:custom-golang-nginx:latest"]);
process_run("buildah", ["push", "custom-golang-nginx:latest", "docker-daemon:localhost/custom-golang-nginx:latest"]);
let tag_result = nerdctl_image_tag("custom-golang-nginx:latest", local_image_name);

View File

@ -2,7 +2,7 @@ print("Running a command using run().log().do()...");
// The .log() method will print the command string to the console before execution.
// This is useful for debugging or tracing which commands are being run.
let result = run("echo This command is logged").log().do();
let result = run("echo This command is logged").log().execute();
print(`Command finished.`);
print(`Success: ${result.success}`);

View File

@ -8,14 +8,23 @@ fn nerdctl_download(){
copy_bin(`/tmp/${name}/*`);
delete(`/tmp/${name}`);
screen_kill("containerd");
let name="containerd";
let url="https://github.com/containerd/containerd/releases/download/v2.1.2/containerd-2.1.2-linux-amd64.tar.gz";
download(url,`/tmp/${name}`,20000);
copy_bin(`/tmp/${name}/bin/*`);
// copy_bin(`/tmp/${name}/bin/*`);
delete(`/tmp/${name}`);
screen_kill("containerd");
let cfg = `
[[registry]]
location = "localhost:5000"
insecure = true
`;
file_write("/etc/containers/registries.conf", dedent(cfg));
screen_new("containerd", "containerd");
sleep(1);
nerdctl_remove_all();
run("nerdctl run -d -p 5000:5000 --name registry registry:2").log().execute();
package_install("buildah");
package_install("runc");

View File

@ -49,6 +49,7 @@ pub mod virt;
pub mod vault;
pub mod zinit_client;
pub mod mycelium;
pub mod net;
// Version information
/// Returns the version of the SAL library

51
src/net/http.rs Normal file
View File

@ -0,0 +1,51 @@
use reqwest::Client;
use std::time::Duration;
// HTTP Checker
pub struct HttpChecker {
client: Client,
url: String,
}
impl HttpChecker {
pub async fn check_url(&self) -> Result<bool, reqwest::Error> {
let res = self.client.get(&self.url).send().await?;
Ok(res.status().is_success())
}
}
// HTTP Checker Builder
pub struct HttpCheckerBuilder {
url: String,
timeout: Duration,
}
impl HttpCheckerBuilder {
pub fn new() -> Self {
Self {
url: "http://localhost".to_string(),
timeout: Duration::from_secs(30),
}
}
pub fn url<S: Into<String>>(mut self, url: S) -> Self {
self.url = url.into();
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
pub fn build(self) -> HttpChecker {
let client = Client::builder()
.timeout(self.timeout)
.build()
.expect("Failed to build HTTP client");
HttpChecker {
client,
url: self.url,
}
}
}

3
src/net/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod ssh;
pub mod tcp;
pub mod http;

133
src/net/ssh.rs Normal file
View File

@ -0,0 +1,133 @@
use russh::client;
use russh_keys::key;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;
// SSH Connection
#[derive(Clone)]
pub struct SshConnection {
session: Arc<client::Handle<Client>>,
}
impl SshConnection {
pub async fn ping(&self) -> Result<(), anyhow::Error> {
let mut channel = self.session.channel_open_session().await?;
channel.exec(true, "ping -c 1 127.0.0.1").await?;
Ok(())
}
}
// SSH Connection Builder
pub struct SshConnectionBuilder {
host: String,
port: u16,
user: String,
password: Option<String>,
key_path: Option<PathBuf>,
use_agent: bool,
timeout: Duration,
}
impl SshConnectionBuilder {
pub fn new() -> Self {
Self {
host: "localhost".to_string(),
port: 22,
user: "root".to_string(),
password: None,
key_path: None,
use_agent: true,
timeout: Duration::from_secs(30),
}
}
pub fn host<S: Into<String>>(mut self, host: S) -> Self {
self.host = host.into();
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = port;
self
}
pub fn user<S: Into<String>>(mut self, user: S) -> Self {
self.user = user.into();
self
}
pub fn password<S: Into<String>>(mut self, password: S) -> Self {
self.password = Some(password.into());
self
}
pub fn key_path(mut self, key_path: PathBuf) -> Self {
self.key_path = Some(key_path);
self
}
pub fn use_agent(mut self, use_agent: bool) -> Self {
self.use_agent = use_agent;
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
pub async fn build(self) -> Result<SshConnection, anyhow::Error> {
let config = Arc::new(client::Config::default());
let sh = Client;
let mut session = client::connect(config, (self.host.as_str(), self.port), sh).await?;
let auth_res = if self.use_agent {
let mut agent = russh_keys::agent::client::AgentClient::connect_env().await?;
let mut keys = agent.request_identities().await?;
if keys.is_empty() {
return Err(anyhow::anyhow!("No identities found in ssh-agent"));
}
let key = keys.remove(0);
let (_agent, authed) = session
.authenticate_future(self.user.as_str(), Arc::new(key), agent)
.await;
authed?
} else if let Some(password) = self.password {
session
.authenticate_password(self.user.as_str(), &password)
.await?
} else if let Some(key_path) = self.key_path {
let key_pair = russh_keys::load_secret_key(key_path, None)?;
session
.authenticate_publickey(self.user.as_str(), Arc::new(key_pair))
.await?
} else {
return Err(anyhow::anyhow!(
"No authentication method specified"
));
};
if !auth_res {
return Err(anyhow::anyhow!("Authentication failed"));
}
Ok(SshConnection {
session: Arc::new(session),
})
}
}
struct Client;
impl client::Handler for Client {
type Error = russh::Error;
fn check_server_key(
&mut self,
_server_public_key: &key::PublicKey,
) -> std::future::Ready<Result<bool, Self::Error>> {
std::future::ready(Ok(true))
}
}

64
src/net/tcp.rs Normal file
View File

@ -0,0 +1,64 @@
use std::net::{SocketAddr, TcpStream};
use std::time::Duration;
// TCP Checker
pub struct TcpChecker {
host: String,
port: u16,
timeout: Duration,
}
impl TcpChecker {
pub fn ping(&self) -> Result<(), std::io::Error> {
let addr = format!("{}:{}", self.host, self.port);
let socket_addr: SocketAddr = addr.parse().expect("Failed to parse socket address");
TcpStream::connect_timeout(&socket_addr, self.timeout)?;
Ok(())
}
pub fn check_port(&self) -> bool {
let addr = format!("{}:{}", self.host, self.port);
let socket_addr: SocketAddr = addr.parse().expect("Failed to parse socket address");
TcpStream::connect_timeout(&socket_addr, self.timeout).is_ok()
}
}
// TCP Checker Builder
pub struct TcpCheckerBuilder {
host: String,
port: u16,
timeout: Duration,
}
impl TcpCheckerBuilder {
pub fn new() -> Self {
Self {
host: "localhost".to_string(),
port: 80,
timeout: Duration::from_secs(1),
}
}
pub fn host<S: Into<String>>(mut self, host: S) -> Self {
self.host = host.into();
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = port;
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
pub fn build(self) -> TcpChecker {
TcpChecker {
host: self.host,
port: self.port,
timeout: self.timeout,
}
}
}