Skip to content

Commit

Permalink
feat(runtime): Remove dependency on clap (#822)
Browse files Browse the repository at this point in the history
  • Loading branch information
kierendavies committed May 15, 2023
1 parent cba9c48 commit 5f0874c
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 40 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ doctest = false
anyhow = { workspace = true }
async-trait = { workspace = true }
chrono = { workspace = true }
clap = { workspace = true }
prost-types = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
Expand Down
50 changes: 23 additions & 27 deletions runtime/src/alpha/args.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
use std::path::PathBuf;
use std::{fmt::Debug, path::PathBuf, str::FromStr};

use clap::{Parser, ValueEnum};
use tonic::transport::{Endpoint, Uri};

#[derive(Parser, Debug)]
#[command(version)]
pub struct Args {
/// Port to start runtime on
#[arg(long)]
pub port: u16,
use crate::args::args;

/// Address to reach provisioner at
#[arg(long, default_value = "http://localhost:3000")]
pub provisioner_address: Endpoint,

/// Type of storage manager to start
#[arg(long, value_enum)]
pub storage_manager_type: StorageManagerType,

/// Path to use for storage manager
#[arg(long)]
pub storage_manager_path: PathBuf,

/// Address to reach the authentication service at
#[arg(long, default_value = "http://127.0.0.1:8008")]
pub auth_uri: Uri,
args! {
pub struct Args {
"--port" => pub port: u16,
"--provisioner-address" => #[arg(default_value = "http://localhost:3000")] pub provisioner_address: Endpoint,
"--storage-manager-type" => pub storage_manager_type: StorageManagerType,
"--storage-manager-path" => pub storage_manager_path: PathBuf,
"--auth-uri" => #[arg(default_value = "http://127.0.0.1:8008")] pub auth_uri: Uri,
}
}

#[derive(Clone, Debug, ValueEnum)]
#[derive(Clone, Debug)]
pub enum StorageManagerType {
/// Use a deloyer artifacts directory
Artifacts,

/// Use a local working directory
WorkingDir,
}

impl FromStr for StorageManagerType {
type Err = ();

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"artifacts" => Ok(StorageManagerType::Artifacts),
"working-dir" => Ok(StorageManagerType::WorkingDir),
_ => Err(()),
}
}
}
3 changes: 1 addition & 2 deletions runtime/src/alpha/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use std::{

use anyhow::Context;
use async_trait::async_trait;
use clap::Parser;
use core::future::Future;
use shuttle_common::{
backends::{
Expand Down Expand Up @@ -51,7 +50,7 @@ use self::args::Args;
mod args;

pub async fn start(loader: impl Loader<ProvisionerFactory> + Send + 'static) {
let args = Args::parse();
let args = Args::parse().expect("could not parse arguments");
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), args.port);

let provisioner_address = args.provisioner_address;
Expand Down
80 changes: 80 additions & 0 deletions runtime/src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#[derive(Debug)]
pub enum Error {
DuplicatedArgument { arg: &'static str },
MissingRequiredArgument { arg: &'static str },
UnexpectedArgument { arg: String },

InvalidValue { arg: &'static str, value: String },
MissingValue { arg: &'static str },
}

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::DuplicatedArgument { arg } => write!(f, "duplicated argument {arg}"),
Self::MissingRequiredArgument { arg } => write!(f, "missing required argument {arg}"),
Self::UnexpectedArgument { arg } => write!(f, "unexpected argument: {arg}"),

Self::InvalidValue { arg, value } => {
write!(f, "invalid value for argument {arg}: {value}")
}
Self::MissingValue { arg } => write!(f, "missing value for argument {arg}"),
}
}
}

impl std::error::Error for Error {}

macro_rules! args {
// Internal rules used to handle optional default values
(@unwrap $arg:literal, $field:ident $(,)?) => {
$field.ok_or_else(|| $crate::args::Error::MissingRequiredArgument { arg: $arg })?
};
(@unwrap $arg:literal, $field:ident, $default:literal) => {
$field.unwrap_or_else(|| $default.parse().unwrap())
};

(
pub struct $struct:ident {
$($arg:literal => $(#[arg(default_value = $default:literal)])? pub $field:ident: $ty:ty),+ $(,)?
}
) => {
#[derive(::std::fmt::Debug)]
pub struct $struct {
$(pub $field: $ty,)+
}

impl $struct {
pub fn parse() -> ::std::result::Result<Self, $crate::args::Error> {
$(let mut $field: ::std::option::Option<$ty> = None;)+

// The first argument is the path of the executable.
let mut args_iter = ::std::env::args().skip(1);
while let ::std::option::Option::Some(arg) = args_iter.next() {
match arg.as_str() {
$($arg => {
if $field.is_some() {
return ::std::result::Result::Err($crate::args::Error::DuplicatedArgument { arg: $arg });
}
let raw_value = args_iter
.next()
.ok_or_else(|| $crate::args::Error::MissingValue { arg: $arg })?;
let value = raw_value.parse().map_err(|_| $crate::args::Error::InvalidValue {
arg: $arg,
value: raw_value,
})?;
$field = ::std::option::Option::Some(value);
})+
_ => return ::std::result::Result::Err($crate::args::Error::UnexpectedArgument { arg }),
}
}

::std::result::Result::Ok($struct {
$($field: $crate::args::args!(@unwrap $arg, $field, $($default)?),)+
})
}
}
}
}

pub(crate) use args;
3 changes: 1 addition & 2 deletions runtime/src/bin/shuttle-next.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::{
time::Duration,
};

use clap::Parser;
use shuttle_common::backends::tracing::{setup_tracing, ExtractPropagationLayer};
use shuttle_proto::runtime::runtime_server::RuntimeServer;
use shuttle_runtime::{AxumWasm, NextArgs};
Expand All @@ -12,7 +11,7 @@ use tracing::trace;

#[tokio::main(flavor = "multi_thread")]
async fn main() {
let args = NextArgs::parse();
let args = NextArgs::parse().unwrap();

setup_tracing(tracing_subscriber::registry(), "shuttle-next");

Expand Down
1 change: 1 addition & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
//! You can also [open an issue or a discussion on GitHub](https://github.com/shuttle-hq/shuttle).
//!
mod alpha;
mod args;
mod logger;
#[cfg(feature = "next")]
mod next;
Expand Down
12 changes: 5 additions & 7 deletions runtime/src/next/args.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use clap::Parser;
use crate::args::args;

#[derive(Parser, Debug)]
#[command(version)]
pub struct NextArgs {
/// Port to start runtime on
#[arg(long)]
pub port: u16,
args! {
pub struct NextArgs {
"--port" => pub port: u16,
}
}

0 comments on commit 5f0874c

Please sign in to comment.