feat: cli enclave build (#137)
This commit is contained in:
parent
eb90043172
commit
3f1cd0b463
11 changed files with 130 additions and 15 deletions
|
@ -10,7 +10,7 @@ keywords = ["blockchain", "cosmos", "tendermint", "cycles", "quartz"]
|
|||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
clap.workspace = true
|
||||
clap = { workspace = true, features=["env"] }
|
||||
color-eyre.workspace = true
|
||||
displaydoc.workspace = true
|
||||
serde.workspace = true
|
||||
|
|
|
@ -27,6 +27,11 @@ pub struct Cli {
|
|||
#[clap(flatten)]
|
||||
pub verbose: Verbosity,
|
||||
|
||||
/// Enable mock SGX mode for testing purposes.
|
||||
/// This flag disables the use of an Intel SGX processor and allows the system to run without remote attestations.
|
||||
#[clap(long, env)]
|
||||
pub mock_sgx: bool,
|
||||
|
||||
/// Main command
|
||||
#[command(subcommand)]
|
||||
pub command: Command,
|
||||
|
@ -36,8 +41,28 @@ pub struct Cli {
|
|||
pub enum Command {
|
||||
/// Create an empty Quartz app from a template
|
||||
Init {
|
||||
/// path to create & init a quartz app, defaults to current path if unspecified
|
||||
/// path to create & init a Quartz app, defaults to current path if unspecified
|
||||
#[clap(long)]
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
/// Subcommands for handling the Quartz app enclave
|
||||
Enclave {
|
||||
#[command(subcommand)]
|
||||
enclave_command: EnclaveCommand,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
pub enum EnclaveCommand {
|
||||
/// Build the Quartz app's enclave
|
||||
Build {
|
||||
/// path to Cargo.toml file of the Quartz app's enclave package, defaults to './enclave/Cargo.toml' if unspecified
|
||||
#[arg(long, default_value = "./enclave/Cargo.toml")]
|
||||
manifest_path: PathBuf,
|
||||
},
|
||||
// Run the Quartz app's enclave
|
||||
Start {
|
||||
#[clap(long)]
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
}
|
|
@ -5,4 +5,6 @@ use thiserror::Error;
|
|||
pub enum Error {
|
||||
/// specified path `{0}` is not a directory
|
||||
PathNotDir(String),
|
||||
/// {0}
|
||||
GenericErr(String),
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
use crate::{cli::Verbosity, error::Error, request::Request, response::Response};
|
||||
use crate::{error::Error, request::Request, response::Response, Config};
|
||||
|
||||
pub mod enclave_build;
|
||||
pub mod init;
|
||||
|
||||
pub trait Handler {
|
||||
type Error;
|
||||
type Response;
|
||||
|
||||
fn handle(self, verbosity: Verbosity) -> Result<Self::Response, Self::Error>;
|
||||
fn handle(self, config: Config) -> Result<Self::Response, Self::Error>;
|
||||
}
|
||||
|
||||
impl Handler for Request {
|
||||
type Error = Error;
|
||||
type Response = Response;
|
||||
|
||||
fn handle(self, verbosity: Verbosity) -> Result<Self::Response, Self::Error> {
|
||||
fn handle(self, config: Config) -> Result<Self::Response, Self::Error> {
|
||||
match self {
|
||||
Request::Init(request) => request.handle(verbosity),
|
||||
Request::Init(request) => request.handle(config),
|
||||
Request::EnclaveBuild(request) => request.handle(config),
|
||||
}
|
||||
.map(Into::into)
|
||||
}
|
||||
|
|
42
cli/src/handler/enclave_build.rs
Normal file
42
cli/src/handler/enclave_build.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use std::process::Command;
|
||||
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
handler::Handler,
|
||||
request::enclave_build::EnclaveBuildRequest,
|
||||
response::{enclave_build::EnclaveBuildResponse, Response},
|
||||
Config,
|
||||
};
|
||||
|
||||
impl Handler for EnclaveBuildRequest {
|
||||
type Error = Error;
|
||||
type Response = Response;
|
||||
|
||||
fn handle(self, config: Config) -> Result<Self::Response, Self::Error> {
|
||||
let mut cargo = Command::new("cargo");
|
||||
let command = cargo
|
||||
.args(["build", "--release"])
|
||||
.args(["--manifest-path", &self.manifest_path.display().to_string()]);
|
||||
|
||||
if config.mock_sgx {
|
||||
debug!("Building with mock-sgx enabled");
|
||||
command.arg("--features=mock-sgx");
|
||||
}
|
||||
|
||||
trace!("🚧 Building enclave ...");
|
||||
let status = command
|
||||
.status()
|
||||
.map_err(|e| Error::GenericErr(e.to_string()))?;
|
||||
|
||||
if !status.success() {
|
||||
return Err(Error::GenericErr(format!(
|
||||
"Couldn't build enclave. {:?}",
|
||||
status
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(EnclaveBuildResponse.into())
|
||||
}
|
||||
}
|
|
@ -1,15 +1,14 @@
|
|||
use tracing::trace;
|
||||
|
||||
use crate::{
|
||||
cli::Verbosity, error::Error, handler::Handler, request::init::InitRequest,
|
||||
response::init::InitResponse,
|
||||
error::Error, handler::Handler, request::init::InitRequest, response::Response, Config,
|
||||
};
|
||||
|
||||
impl Handler for InitRequest {
|
||||
type Error = Error;
|
||||
type Response = InitResponse;
|
||||
type Response = Response;
|
||||
|
||||
fn handle(self, _verbosity: Verbosity) -> Result<Self::Response, Self::Error> {
|
||||
fn handle(self, _config: Config) -> Result<Self::Response, Self::Error> {
|
||||
trace!("initializing directory structure...");
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ use tracing_subscriber::{util::SubscriberInitExt, EnvFilter};
|
|||
|
||||
use crate::{cli::Cli, handler::Handler, request::Request};
|
||||
|
||||
pub struct Config {
|
||||
pub mock_sgx: bool,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
||||
|
@ -48,7 +52,9 @@ fn main() -> Result<()> {
|
|||
|
||||
// Each `Request` defines an associated `Handler` (i.e. logic) and `Response`. All handlers are
|
||||
// free to log to the terminal and these logs are sent to `stderr`.
|
||||
let response = request.handle(args.verbose)?;
|
||||
let response = request.handle(Config {
|
||||
mock_sgx: args.mock_sgx,
|
||||
})?;
|
||||
|
||||
// `Handlers` must use `Responses` to output to `stdout`.
|
||||
println!(
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
use crate::{cli::Command, error::Error, request::init::InitRequest};
|
||||
use crate::{
|
||||
cli::{Command, EnclaveCommand},
|
||||
error::Error,
|
||||
request::{enclave_build::EnclaveBuildRequest, init::InitRequest},
|
||||
};
|
||||
|
||||
pub mod enclave_build;
|
||||
pub mod init;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Request {
|
||||
Init(InitRequest),
|
||||
EnclaveBuild(EnclaveBuildRequest),
|
||||
}
|
||||
|
||||
impl TryFrom<Command> for Request {
|
||||
|
@ -12,8 +18,13 @@ impl TryFrom<Command> for Request {
|
|||
|
||||
fn try_from(cmd: Command) -> Result<Self, Self::Error> {
|
||||
match cmd {
|
||||
Command::Init { path } => InitRequest::try_from(path),
|
||||
Command::Init { path } => InitRequest::try_from(path).map(Into::into),
|
||||
Command::Enclave { enclave_command } => match enclave_command {
|
||||
EnclaveCommand::Build { manifest_path } => {
|
||||
Ok(EnclaveBuildRequest { manifest_path }.into())
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
}
|
||||
.map(Into::into)
|
||||
}
|
||||
}
|
||||
|
|
14
cli/src/request/enclave_build.rs
Normal file
14
cli/src/request/enclave_build.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::request::Request;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EnclaveBuildRequest {
|
||||
pub manifest_path: PathBuf,
|
||||
}
|
||||
|
||||
impl From<EnclaveBuildRequest> for Request {
|
||||
fn from(request: EnclaveBuildRequest) -> Self {
|
||||
Self::EnclaveBuild(request)
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::response::init::InitResponse;
|
||||
use crate::response::{enclave_build::EnclaveBuildResponse, init::InitResponse};
|
||||
|
||||
pub mod enclave_build;
|
||||
pub mod init;
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum Response {
|
||||
Init(InitResponse),
|
||||
EnclaveBuild(EnclaveBuildResponse),
|
||||
}
|
||||
|
|
12
cli/src/response/enclave_build.rs
Normal file
12
cli/src/response/enclave_build.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::response::Response;
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct EnclaveBuildResponse;
|
||||
|
||||
impl From<EnclaveBuildResponse> for Response {
|
||||
fn from(response: EnclaveBuildResponse) -> Self {
|
||||
Self::EnclaveBuild(response)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue