This commit is contained in:
Hamcha 2024-04-13 01:36:32 +02:00
commit 3009cf3a55
Signed by: hamcha
GPG Key ID: 1669C533B8CF6D89
15 changed files with 992 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
.vscode

526
Cargo.lock generated Normal file
View File

@ -0,0 +1,526 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "argh"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
dependencies = [
"argh_derive",
"argh_shared",
]
[[package]]
name = "argh_derive"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
dependencies = [
"argh_shared",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "argh_shared"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
dependencies = [
"serde",
]
[[package]]
name = "autocfg"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "backtrace"
version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytes"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]]
name = "cc"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libstax"
version = "0.1.0"
dependencies = [
"serde_json",
"thiserror",
"tokio",
]
[[package]]
name = "lock_api"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "memchr"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "object"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.48.5",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "proc-macro2"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "stax-cli"
version = "0.1.0"
dependencies = [
"argh",
"libstax",
"tokio",
]
[[package]]
name = "syn"
version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.4",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm 0.52.4",
"windows_aarch64_msvc 0.52.4",
"windows_i686_gnu 0.52.4",
"windows_i686_msvc 0.52.4",
"windows_x86_64_gnu 0.52.4",
"windows_x86_64_gnullvm 0.52.4",
"windows_x86_64_msvc 0.52.4",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"

12
Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "stax-cli"
version = "0.1.0"
edition = "2021"
[workspace]
members = ["libstax"]
[dependencies]
tokio = { version = "1", features = ["full"] }
argh = "0.1.12"
libstax = { path = "libstax" }

9
libstax/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "libstax"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1", features = [] }
serde_json = { version = "1", features = ["std"] }
thiserror = { version = "1", features = [] }

128
libstax/src/compose.rs Normal file
View File

@ -0,0 +1,128 @@
use serde_json::{to_string_pretty, Value};
use std::{backtrace::Backtrace, collections::HashMap, path::PathBuf, process::Stdio};
use tokio::io::AsyncWriteExt;
use crate::error::{Error, Result};
pub type StackMap = HashMap<String, String>;
pub fn parse_compose_stacks_output(bytes: Vec<u8>) -> Result<StackMap> {
let json_output = serde_json::from_slice::<Value>(&bytes)?;
let object = json_output.as_object().ok_or_else(|| Error::FormatError {
message: "not an object".to_string(),
backtrace: Backtrace::capture(),
})?;
let mut stacks = HashMap::new();
for (key, value) in object.iter() {
stacks.insert(key.to_string(), to_string_pretty(value)?);
}
Ok(stacks)
}
pub async fn export_compose_stacks(stacks: StackMap, output_dir: &PathBuf) -> Result<()> {
// Create output directory if it doesn't exist
if !output_dir.exists() {
tokio::fs::create_dir_all(output_dir).await?;
}
// Create a docker-compose file for each stack
for (stack_name, stack) in stacks.iter() {
let stack_file_name = format!("{}.json", stack_name);
let stack_file_path = output_dir.join(stack_file_name);
tokio::fs::write(&stack_file_path, stack).await?;
}
Ok(())
}
pub enum ComposeOperation {
Start,
Stop,
Restart,
Down,
Remove,
Pause,
Unpause,
Kill,
Create,
}
pub struct ComposeRunner {
compose_binary_path: PathBuf,
}
impl ComposeRunner {
pub fn new(compose_binary_path: PathBuf) -> Self {
Self {
compose_binary_path,
}
}
pub async fn deploy_stack(&self, project_name: &str, stack_contents: &str) -> Result<()> {
// Run the docker compose command and pipe stdout/stderr
let mut docker_command = tokio::process::Command::new(&self.compose_binary_path)
.args(&[
"compose",
"-p",
project_name,
"-f",
"-",
"up",
"-d",
"--no-color",
"--remove-orphans",
])
.stdin(Stdio::piped())
.spawn()?;
// Write contents to stdin
docker_command
.stdin
.take()
.ok_or(Error::ExecutionError {
message: "no stdin".to_string(),
backtrace: Backtrace::capture(),
})?
.write_all(stack_contents.as_bytes())
.await?;
let output = docker_command.wait_with_output().await?;
if !output.status.success() {
return Err(Error::DeployError {
message: String::from_utf8_lossy(&output.stderr).to_string(),
backtrace: Backtrace::capture(),
});
}
Ok(())
}
pub async fn stack_op(&self, project_name: &str, operation: ComposeOperation) {
let _ = tokio::process::Command::new(&self.compose_binary_path)
.args(&[
"compose",
"-p",
project_name,
"-f",
"-",
match operation {
ComposeOperation::Start => "start",
ComposeOperation::Stop => "stop",
ComposeOperation::Restart => "restart",
ComposeOperation::Down => "restart",
ComposeOperation::Remove => "rm",
ComposeOperation::Pause => "pause",
ComposeOperation::Kill => "kill",
ComposeOperation::Create => "create",
ComposeOperation::Unpause => "unpause",
},
])
.stdin(Stdio::piped())
.spawn()
.unwrap()
.wait()
.await;
}
}

64
libstax/src/deno.rs Normal file
View File

@ -0,0 +1,64 @@
use crate::compose::{export_compose_stacks, parse_compose_stacks_output, StackMap};
use crate::error::{Error, Result};
use std::{backtrace::Backtrace, path::PathBuf};
macro_rules! run_deno {
($interpreter_path: expr) => {
tokio::process::Command::new($interpreter_path)
.env("NO_COLOR", "true")
.env("DENO_NO_UPDATE_CHECK", "true")
};
}
pub struct ScriptRunner {
interpreter_path: PathBuf,
}
impl ScriptRunner {
pub fn new(interpreter_path: PathBuf) -> Self {
Self { interpreter_path }
}
pub async fn check_script(&self, script_path: &str) -> Result<()> {
let output = run_deno!(&self.interpreter_path)
.args(&["check", "-q", script_path])
.output()
.await?;
if !output.status.success() {
return Err(Error::ScriptError {
message: String::from_utf8_lossy(&output.stderr).to_string(),
backtrace: Backtrace::capture(),
});
}
Ok(())
}
pub async fn run_script(&self, script_path: &str) -> Result<Vec<u8>> {
let output = run_deno!(&self.interpreter_path)
.args(&["run", "--no-prompt", "-q", "--no-check", script_path])
.output()
.await?;
if !output.status.success() {
return Err(Error::ExecutionError {
message: String::from_utf8_lossy(&output.stderr).to_string(),
backtrace: Backtrace::capture(),
});
}
Ok(output.stdout)
}
pub async fn run_and_export(&self, script_path: &str, output_dir: &PathBuf) -> Result<()> {
let output = self.run_script(script_path).await?;
let stacks = parse_compose_stacks_output(output)?;
export_compose_stacks(stacks, output_dir).await
}
pub async fn run_and_parse(&self, script_path: &str) -> Result<StackMap> {
let output = self.run_script(script_path).await?;
parse_compose_stacks_output(output)
}
}

46
libstax/src/error.rs Normal file
View File

@ -0,0 +1,46 @@
use std::{backtrace::Backtrace, io};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("IO error: {source}")]
Io {
#[from]
source: io::Error,
backtrace: Backtrace,
},
#[error("Script error: {message}")]
ScriptError {
message: String,
backtrace: Backtrace,
},
#[error("Run error: {message}")]
ExecutionError {
message: String,
backtrace: Backtrace,
},
#[error("Deploy error: {message}")]
DeployError {
message: String,
backtrace: Backtrace,
},
#[error("Format error: {message}")]
FormatError {
message: String,
backtrace: Backtrace,
},
#[error("JSON error: {source}")]
JSONError {
#[from]
source: serde_json::Error,
backtrace: Backtrace,
},
}
pub type Result<T> = std::result::Result<T, Error>;

5
libstax/src/lib.rs Normal file
View File

@ -0,0 +1,5 @@
#![feature(error_generic_member_access)]
pub mod compose;
pub mod deno;
mod error;

2
rust-toolchain.toml Normal file
View File

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

45
src/deploy.rs Normal file
View File

@ -0,0 +1,45 @@
use argh::FromArgs;
use libstax::{compose, deno::ScriptRunner};
use std::path::PathBuf;
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "deploy")]
/// Dry run (print stacks to stdout)
pub(crate) struct Arguments {
/// script to run
#[argh(positional)]
script_path: String,
/// path to Typescript interpreter (Deno)
#[argh(option, default = "PathBuf::from(\"deno\")")]
interpreter_path: PathBuf,
/// path to docker binary
#[argh(option, default = "PathBuf::from(\"docker\")")]
docker_cli_path: PathBuf,
}
pub(crate) async fn deploy(args: Arguments) {
let runner = ScriptRunner::new(args.interpreter_path);
runner
.check_script(&args.script_path)
.await
.expect("Failed to check script");
let stacks = runner
.run_and_parse(&args.script_path)
.await
.expect("Failed to run script");
let compose = compose::ComposeRunner::new(args.docker_cli_path);
for (name, contents) in stacks {
println!("<> Deploying {} <>", name);
compose
.deploy_stack(&name, &contents)
.await
.expect("Failed to deploy stack");
}
}

32
src/dryrun.rs Normal file
View File

@ -0,0 +1,32 @@
use argh::FromArgs;
use libstax::deno::ScriptRunner;
use std::path::PathBuf;
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "dry-run")]
/// Dry run (print stacks to stdout)
pub(crate) struct Arguments {
/// script to run
#[argh(positional)]
script_path: String,
/// path to Typescript interpreter (Deno)
#[argh(option, default = "PathBuf::from(\"deno\")")]
interpreter_path: PathBuf,
}
pub(crate) async fn dry_run(args: Arguments) {
let runner = ScriptRunner::new(args.interpreter_path);
runner
.check_script(&args.script_path)
.await
.expect("Failed to check script");
let stacks_output = runner
.run_script(&args.script_path)
.await
.expect("Failed to run script");
println!("{}", String::from_utf8_lossy(&stacks_output));
}

34
src/export.rs Normal file
View File

@ -0,0 +1,34 @@
use argh::FromArgs;
use libstax::deno::ScriptRunner;
use std::path::PathBuf;
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "export")]
/// Export stacks
pub(crate) struct Arguments {
/// path to output directory
#[argh(option, short = 'o', default = "PathBuf::from(\"output\")")]
output_dir: PathBuf,
/// path to Typescript interpreter (Deno)
#[argh(option, default = "PathBuf::from(\"deno\")")]
interpreter_path: PathBuf,
/// script to run
#[argh(positional)]
script_path: String,
}
pub(crate) async fn export(args: Arguments) {
let runner = ScriptRunner::new(args.interpreter_path);
runner
.check_script(&args.script_path)
.await
.expect("Failed to check script");
runner
.run_and_export(&args.script_path, &args.output_dir)
.await
.expect("Failed to export stacks");
}

44
src/main.rs Normal file
View File

@ -0,0 +1,44 @@
use argh::FromArgs;
use std::path::PathBuf;
mod deploy;
mod dryrun;
mod export;
mod op;
#[derive(FromArgs, PartialEq, Debug)]
/// Command line app for staxman actions
struct ScriptArguments {
/// project root
#[argh(option, short = 'd')]
project_root: Option<PathBuf>,
#[argh(subcommand)]
action: ActionCommands,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum ActionCommands {
Export(export::Arguments),
DryRun(dryrun::Arguments),
Deploy(deploy::Arguments),
Op(op::Arguments),
}
#[tokio::main]
async fn main() {
let args: ScriptArguments = argh::from_env();
// Set current directory to project root
if let Some(project_root) = args.project_root {
std::env::set_current_dir(&project_root).expect("Failed to set current directory");
}
match args.action {
ActionCommands::DryRun(args) => dryrun::dry_run(args).await,
ActionCommands::Export(args) => export::export(args).await,
ActionCommands::Deploy(args) => deploy::deploy(args).await,
ActionCommands::Op(args) => op::op(args).await,
}
}

43
src/op.rs Normal file
View File

@ -0,0 +1,43 @@
use argh::FromArgs;
use libstax::compose::ComposeRunner;
use std::path::PathBuf;
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "op")]
/// Execute operation on a stack
pub(crate) struct Arguments {
/// project name
#[argh(positional)]
project: String,
/// operation
#[argh(positional)]
op: String,
/// path to docker binary
#[argh(option, default = "PathBuf::from(\"docker\")")]
docker_cli_path: PathBuf,
}
pub(crate) async fn op(args: Arguments) {
ComposeRunner::new(args.docker_cli_path)
.stack_op(
&args.project,
match args.op.as_str() {
"start" => libstax::compose::ComposeOperation::Start,
"stop" => libstax::compose::ComposeOperation::Stop,
"restart" => libstax::compose::ComposeOperation::Restart,
"down" => libstax::compose::ComposeOperation::Down,
"rm" => libstax::compose::ComposeOperation::Remove,
"pause" => libstax::compose::ComposeOperation::Pause,
"kill" => libstax::compose::ComposeOperation::Kill,
"create" => libstax::compose::ComposeOperation::Create,
"unpause" => libstax::compose::ComposeOperation::Unpause,
_ => {
eprintln!("Unknown operation: {}", args.op);
std::process::exit(1);
}
},
)
.await;
}

0
src/teardown.rs Normal file
View File