with builder

This commit is contained in:
Kasper Juul Hermansen 2022-11-22 23:12:10 +01:00
parent b7a0e0b96e
commit 367fa16fd7
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
12 changed files with 254 additions and 13 deletions

Binary file not shown.

View File

@ -1,7 +1,7 @@
use std::path::{self, PathBuf}; use std::path::PathBuf;
use clap::{Arg, ArgAction, ArgMatches, Command}; use clap::{Arg, ArgAction, ArgMatches, Command};
use octopush_core::schema::{self, models::Action}; use octopush_core::schema;
use octopush_infra::service_register::ServiceRegister; use octopush_infra::service_register::ServiceRegister;
pub fn execute_cmd() -> Command { pub fn execute_cmd() -> Command {
@ -53,7 +53,14 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
paths.push(path); paths.push(path);
} }
kk for path in paths {
for action in actions.clone() {
service_register
.executor
.execute(path.clone(), action_path.clone(), action)
.await?;
}
}
} }
} }

View File

@ -0,0 +1,36 @@
use std::{path::PathBuf, sync::Arc};
use async_trait::async_trait;
use crate::schema::models::Action;
use super::{
builders::golang_bin::{GolangBinBuild, GolangBinBuildOpts},
Builder, DynRunnableBin,
};
pub struct BuilderCapabilities;
impl BuilderCapabilities {
pub fn new() -> Self {
Self {}
}
}
#[async_trait]
impl Builder for BuilderCapabilities {
async fn build(&self, action_path: PathBuf, action: Action) -> eyre::Result<DynRunnableBin> {
match action {
Action::Go { entry } => {
let bin = GolangBinBuild::new()
.build(GolangBinBuildOpts {
entry,
src_path: action_path,
})
.await?;
Ok(Arc::new(bin))
}
}
}
}

View File

@ -0,0 +1,55 @@
use std::path::PathBuf;
use async_trait::async_trait;
use crate::{
builder::RunnableBin,
shell::{execute_shell, print_res},
};
pub struct GolangBinBuildOpts {
pub entry: String,
pub src_path: PathBuf,
}
pub struct GolangBinBuild;
impl GolangBinBuild {
pub fn new() -> Self {
Self {}
}
pub async fn build(&self, opts: GolangBinBuildOpts) -> eyre::Result<GolangBin> {
tracing::trace!(
src = opts.src_path.to_string_lossy().to_string(),
entry = opts.entry,
"build golang_bin"
);
let res = execute_shell(
format!("go build {}", opts.entry),
Some(opts.src_path.clone()),
)
.await?;
print_res("golang_bin".into(), res);
Ok(GolangBin::new(opts.src_path))
}
}
pub struct GolangBin {
path: PathBuf,
}
impl GolangBin {
fn new(path: PathBuf) -> Self {
Self { path }
}
}
#[async_trait]
impl RunnableBin for GolangBin {
async fn run(&self) -> eyre::Result<()> {
todo!("not implemented")
}
}

View File

@ -0,0 +1 @@
pub mod golang_bin;

View File

@ -0,0 +1,22 @@
pub mod builder_capabilities;
mod builders;
use std::{path::PathBuf, sync::Arc};
use async_trait::async_trait;
use crate::schema::models::Action;
#[async_trait]
pub trait RunnableBin {
async fn run(&self) -> eyre::Result<()>;
}
pub type DynRunnableBin = Arc<dyn RunnableBin + Send + Sync>;
#[async_trait]
pub trait Builder {
async fn build(&self, action_path: PathBuf, action: Action) -> eyre::Result<DynRunnableBin>;
}
pub type DynBuilder = Arc<dyn Builder + Send + Sync>;

View File

@ -1,16 +1,43 @@
use std::path::PathBuf;
use async_trait::async_trait; use async_trait::async_trait;
use crate::schema::models::Action; use crate::{builder::DynBuilder, schema::models::Action};
use super::executor::Executor; use super::{
executor::Executor,
executors::golang::{GolangExecutor, GolangExecutorOpts},
};
pub struct DefaultExecutor; pub struct DefaultExecutor {
builder: DynBuilder,
}
impl DefaultExecutor {
pub fn new(builder: DynBuilder) -> Self {
Self { builder }
}
}
#[async_trait] #[async_trait]
impl Executor for DefaultExecutor { impl Executor for DefaultExecutor {
async fn execute(&self, action: Action) -> eyre::Result<()> { async fn execute(
&self,
victim_path: PathBuf,
action_path: PathBuf,
action: Action,
) -> eyre::Result<()> {
let bin = self.builder.build(action_path, action.clone()).await?;
match action { match action {
Action::Go { entry } => todo!(), Action::Go { entry } => {
GolangExecutor::new()
.execute(GolangExecutorOpts {
bin,
entry,
src_path: victim_path,
})
.await?
}
} }
Ok(()) Ok(())

View File

@ -1,4 +1,4 @@
use std::sync::Arc; use std::{path::PathBuf, sync::Arc};
use async_trait::async_trait; use async_trait::async_trait;
@ -6,7 +6,12 @@ use crate::schema::models::Action;
#[async_trait] #[async_trait]
pub trait Executor { pub trait Executor {
async fn execute(&self, action: Action) -> eyre::Result<()>; async fn execute(
&self,
victim_path: PathBuf,
action_path: PathBuf,
action: Action,
) -> eyre::Result<()>;
} }
pub type DynExecutor = Arc<dyn Executor + Send + Sync>; pub type DynExecutor = Arc<dyn Executor + Send + Sync>;

View File

@ -0,0 +1,21 @@
use std::path::PathBuf;
use crate::builder::DynRunnableBin;
pub struct GolangExecutorOpts {
pub bin: DynRunnableBin,
pub entry: String,
pub src_path: PathBuf,
}
pub struct GolangExecutor;
impl GolangExecutor {
pub fn new() -> Self {
Self {}
}
pub async fn execute(&self, opts: GolangExecutorOpts) -> eyre::Result<()> {
Ok(())
}
}

View File

@ -1,4 +1,6 @@
pub mod git; pub mod builder;
pub mod storage;
pub mod schema;
pub mod executor; pub mod executor;
pub mod git;
pub mod schema;
mod shell;
pub mod storage;

View File

@ -0,0 +1,57 @@
use std::{path::PathBuf, process::Stdio};
use eyre::Context;
use tokio::io::{AsyncBufReadExt, BufReader};
pub async fn execute_shell(cmd: String, path: Option<PathBuf>) -> eyre::Result<Vec<String>> {
let mut command = tokio::process::Command::new("sh");
let command = command.arg("-c");
let command = if let Some(path) = path {
command.current_dir(path)
} else {
command
};
let command = command.arg(format!("{}", cmd));
let command = command.stdout(Stdio::piped());
let mut child = command.spawn()?;
let stdout = child
.stdout
.take()
.ok_or(eyre::anyhow!("could not take stdout of command"))?;
let mut reader = BufReader::new(stdout).lines();
tokio::spawn(async move {
let status = child
.wait()
.await
.context(eyre::anyhow!("child process encountered an error"))
.unwrap();
if !status.success() {
tracing::error!(
cmd,
status = status.to_string(),
"child program encountered an error"
);
}
});
let mut lines: Vec<String> = Vec::new();
while let Some(line) = reader.next_line().await? {
lines.push(line)
}
Ok(lines)
}
pub fn print_res(scope: String, res: Vec<String>) {
for r in res {
tracing::debug!("{}: {}", scope, r);
}
}

View File

@ -1,6 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use octopush_core::{ use octopush_core::{
builder::{builder_capabilities::BuilderCapabilities, DynBuilder},
executor::{default_executor::DefaultExecutor, executor::DynExecutor},
git::{github::GitHubGitProvider, DynGitProvider}, git::{github::GitHubGitProvider, DynGitProvider},
schema::parser::{DefaultSchemaParser, DynSchemaParser}, schema::parser::{DefaultSchemaParser, DynSchemaParser},
storage::{local::LocalStorageEngine, DynStorageEngine}, storage::{local::LocalStorageEngine, DynStorageEngine},
@ -10,6 +12,8 @@ pub struct ServiceRegister {
pub storage_engine: DynStorageEngine, pub storage_engine: DynStorageEngine,
pub git_provider: DynGitProvider, pub git_provider: DynGitProvider,
pub schema_parser: DynSchemaParser, pub schema_parser: DynSchemaParser,
pub builder: DynBuilder,
pub executor: DynExecutor,
} }
impl ServiceRegister { impl ServiceRegister {
@ -17,11 +21,15 @@ impl ServiceRegister {
let storage_engine = Arc::new(LocalStorageEngine::new("/tmp/octopush".into())); let storage_engine = Arc::new(LocalStorageEngine::new("/tmp/octopush".into()));
let git_provider = Arc::new(GitHubGitProvider::new(storage_engine.clone())); let git_provider = Arc::new(GitHubGitProvider::new(storage_engine.clone()));
let schema_parser = Arc::new(DefaultSchemaParser::new()); let schema_parser = Arc::new(DefaultSchemaParser::new());
let builder = Arc::new(BuilderCapabilities::new());
let executor = Arc::new(DefaultExecutor::new(builder.clone()));
Self { Self {
storage_engine, storage_engine,
git_provider, git_provider,
schema_parser, schema_parser,
builder,
executor,
} }
} }