feat: add simple health check

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-08-24 17:22:45 +02:00
commit f61d0bbf12
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
13 changed files with 2363 additions and 0 deletions

2
.gitignore vendored Normal file
View File

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

2034
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

16
Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[workspace]
members = ["crates/*"]
resolver = "2"
[workspace.dependencies]
churn = { path = "crates/churn" }
churn-agent = { path = "crates/churn-agent" }
churn-server = { path = "crates/churn-server" }
anyhow = { version = "1.0.71" }
tokio = { version = "1", features = ["full"] }
tracing = { version = "0.1", features = ["log"] }
tracing-subscriber = { version = "0.3.17" }
clap = { version = "4.3.4", features = ["derive", "env"] }
dotenv = { version = "0.15.0" }
axum = { version = "0.6.18" }

View File

@ -0,0 +1,15 @@
[package]
name = "churn-agent"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow.workspace = true
tokio.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
clap.workspace = true
dotenv.workspace = true
axum.workspace = true

View File

@ -0,0 +1,58 @@
use std::net::SocketAddr;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None, subcommand_required = true)]
struct Command {
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
Daemon {
#[arg(env = "CHURN_ADDR", long)]
host: SocketAddr,
},
Connect {
/// agent name is the hostname which other agents or servers can resolve and connect via. It should be unique
#[arg(env = "CHURN_AGENT_NAME", long)]
agent_name: String,
#[arg(env = "CHURN_ADDR", long)]
host: SocketAddr,
#[arg(env = "CHURN_TOKEN", long)]
token: String,
},
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
tracing_subscriber::fmt::init();
let cli = Command::parse();
handle_command(cli).await?;
Ok(())
}
async fn handle_command(cmd: Command) -> anyhow::Result<()> {
match cmd.command {
Some(Commands::Daemon { host }) => {
tracing::info!("starting agent server on {}", host);
tokio::time::sleep(std::time::Duration::from_secs(60)).await;
Ok(())
}
Some(Commands::Connect {
host,
token,
agent_name,
}) => todo!(),
None => todo!(),
}
}

View File

@ -0,0 +1,15 @@
[package]
name = "churn-server"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow.workspace = true
tokio.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
clap.workspace = true
dotenv.workspace = true
axum.workspace = true

View File

@ -0,0 +1,64 @@
use std::net::SocketAddr;
use axum::response::IntoResponse;
use axum::routing::{get, post};
use axum::Router;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None, subcommand_required = true)]
struct Command {
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
Serve {
#[arg(env = "SERVICE_HOST", long, default_value = "127.0.0.1:3000")]
host: SocketAddr,
},
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
tracing_subscriber::fmt::init();
let cli = Command::parse();
match cli.command {
Some(Commands::Serve { host }) => {
tracing::info!("Starting service");
let app = Router::new().nest(
"/agent",
Router::new()
.route("/enroll", post(enroll))
.route("/ping", post(ping))
.route("/events", post(get_tasks)),
);
tracing::info!("listening on {}", host);
axum::Server::bind(&host)
.serve(app.into_make_service())
.await
.unwrap();
}
None => {}
}
Ok(())
}
async fn enroll() -> impl IntoResponse {
todo!()
}
async fn ping() -> impl IntoResponse {
todo!()
}
async fn get_tasks() -> impl IntoResponse {
todo!()
}

1
crates/churn/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

13
crates/churn/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "churn"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow.workspace = true
tokio.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
clap.workspace = true
dotenv.workspace = true
axum.workspace = true

63
crates/churn/src/main.rs Normal file
View File

@ -0,0 +1,63 @@
use std::net::SocketAddr;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None, subcommand_required = true)]
struct Command {
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
Bootstrap {
#[arg(env = "CHURN_AGENT", long)]
host: String,
#[arg(env = "CHURN_SERVER", long)]
server: String,
#[arg(env = "CHURN_SERVER_TOKEN", long)]
server_token: String,
},
Health {
#[arg(env = "CHURN_SERVER", long)]
server: String,
#[arg(env = "CHURN_AGENT", long)]
agent: String,
},
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
tracing_subscriber::fmt::init();
let cli = Command::parse();
handle_command(cli).await?;
Ok(())
}
async fn handle_command(cmd: Command) -> anyhow::Result<()> {
if let Some(cmd) = cmd.command {
match cmd {
Commands::Bootstrap {
host,
server,
server_token,
} => todo!(),
Commands::Health { server, agent } => {
tracing::info!("connecting to server: {}", server);
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
tracing::info!("connecting to agent: {}", agent);
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
Ok(())
}
}
} else {
panic!("no command supplied")
}
}

View File

@ -0,0 +1,12 @@
[package]
name = "churning"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dagger-sdk = "0.2.2"
dagger-rust = "0.2.0"
tokio.workspace = true
eyre = "*"

View File

@ -0,0 +1,63 @@
use std::{path::PathBuf, sync::Arc};
use dagger_rust::build::{RustVersion, SlimImage};
use dagger_sdk::Query;
#[tokio::main]
async fn main() -> eyre::Result<()> {
let client = dagger_sdk::connect().await?;
let agent = build_container(client.clone(), "churn-agent").await?;
let agent = agent
.with_exec(vec!["churn-agent", "daemon", "--host", "0.0.0.0:3000"])
.with_exposed_port(3000);
let cli = build_container(client.clone(), "churn").await?;
let server = build_container(client.clone(), "churn-server").await?;
let server = server
.with_exec(vec!["churn-server", "serve", "--host", "0.0.0.0:3000"])
.with_exposed_port(3000);
cli.with_service_binding("churn-agent", agent.id().await?)
.with_service_binding("churn-server", server.id().await?)
.with_exec(vec![
"churn",
"health",
"--server",
"churn-server:3000",
"--agent",
"churn-agent:3000",
])
.exit_code()
.await?;
Ok(())
}
async fn build_container(
client: Arc<Query>,
bin_name: &str,
) -> eyre::Result<dagger_sdk::Container> {
let crates = &["crates/*", "ci"];
let debian_deps = &["libssl-dev", "pkg-config", "openssl", "git", "jq"];
let debian_image = "debian:bullseye".to_string();
let images = dagger_rust::build::RustBuild::new(client.clone())
.build_release(
None::<PathBuf>,
RustVersion::Nightly,
crates,
debian_deps,
vec![SlimImage::Debian {
image: debian_image,
deps: debian_deps
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>(),
architecture: dagger_rust::build::BuildArchitecture::Arm64,
}],
&bin_name,
)
.await?;
Ok(images.first().take().unwrap().clone())
}

7
cuddle.yaml Normal file
View File

@ -0,0 +1,7 @@
# yaml-language-server: $schema=https://git.front.kjuulh.io/kjuulh/cuddle/raw/branch/main/schemas/base.json
base: "git@git.front.kjuulh.io:kjuulh/cuddle-base.git"
vars:
service: "churn"
registry: kasperhermansen