Skip to content

Commit

Permalink
feat: read both stderr and stdout
Browse files Browse the repository at this point in the history
chore: testing InternalApi.create_workspace()

Signed-off-by: WoodenMaiden <[email protected]>
  • Loading branch information
WoodenMaiden committed Mar 28, 2023
1 parent 45cb688 commit dd9bf23
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 42 deletions.
1 change: 0 additions & 1 deletion agent/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ edition = "2021"
serialport = "4.2.0"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"
unshare = "0.7.0"
log = "0.4.0"
anyhow = "1.0.69"
env_logger = "0.10.0"
2 changes: 1 addition & 1 deletion agent/lib/src/external_api/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ pub struct FileModel {
#[derive(Deserialize, Serialize, Debug)]
pub struct CodeEntry {
pub files: Vec<FileModel>,
pub script: Vec<String>,
pub script: Vec<String>, // All commands to execute at startup
}
4 changes: 2 additions & 2 deletions agent/lib/src/internal_api/model.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::path::PathBuf;

use serde::{Deserialize, Serialize};
use unshare;

#[derive(Deserialize, Serialize, Debug)]
pub struct FileModel {
Expand Down Expand Up @@ -39,9 +38,10 @@ impl CodeReturn {

#[derive(Debug)]
pub enum InternalError {
CmdSpawn(unshare::Error),
CmdSpawn,
ChildWait(std::io::Error),
ChildExitError(i32),
InvalidExitCode,
StdoutRead,
StderrRead,
}
139 changes: 103 additions & 36 deletions agent/lib/src/internal_api/service.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
use super::model::{CodeReturn, InternalError};
use crate::{external_api::model::CodeEntry, internal_api::model::FileModel};
use std::{process::Command, fs::File, path::{PathBuf, Path}};
use anyhow::{anyhow, Result};
use log::{error, info};
use crate::{external_api::model::CodeEntry, internal_api::model::FileModel};
use std::io::Write;
use std::{
fs::File,
io::{BufReader, Read},
path::{Path, PathBuf},
};
use unshare::Command;
use super::model::{CodeReturn, InternalError};

const WORKSPACE_PATH: &str = "/tmp";

Expand Down Expand Up @@ -104,34 +99,106 @@ impl InternalApi {
}

pub fn run(&mut self) -> Result<CodeReturn, InternalError> {
let code = Command::new("/bin/sh")
.args(&["-c", "echo", "'Hello world'"])
.spawn()
.map_err(InternalError::CmdSpawn)?
.stdout;

// .wait().map_err(InternalError::ChildWait)?.fmt(f)
// .wait()
// .map_err(InternalError::ChildWait)?
// .code();

if let Some(code) = code {
// if code != 0 {
// return Err(InternalError::ChildExitError(code));
// }
let mut stdout_reader = BufReader::new(code);
let mut stdout_output = String::new();
println!("Internal API: Reading stdout");
stdout_reader
.read_to_string(&mut stdout_output)
.map_err(|_| InternalError::StdoutRead)?;
// println!("{}", stdout_output);
let result = CodeReturn::new(stdout_output, "stderr".to_string(), 0);

Ok(result)
info!("Running code");

// Running the latest command in vector for now

let child_process = Command::new("/bin/sh")
.args(["-c",
self.code_entry.script.last().ok_or(
InternalError::CmdSpawn
)?.as_str()
])
.current_dir(WORKSPACE_PATH)
.output()
.map_err(|_|InternalError::CmdSpawn)?;

info!("Code execution finished, gathering outputs and exit code");

let exit_code = child_process.status.code().ok_or(
InternalError::InvalidExitCode
)?;
let stdout = String::from_utf8(child_process.stdout).map_err(
|_| InternalError::StdoutRead
)?;
let stderr = String::from_utf8(child_process.stderr).map_err(
|_| InternalError::StderrRead
)?;

Ok(CodeReturn::new(stdout, stderr, exit_code))
}

}

#[cfg(test)]
mod tests {
use std::fs::File;
use std::io::Read;
use crate::external_api::model::FileModel;
use super::*;

fn random_usize(max: usize) -> usize {
let mut f = File::open("/dev/urandom").unwrap();
let mut buf = [0u8; 1];
f.read_exact(&mut buf).unwrap();
let value = buf[0] as usize;

if value < max {
max
} else {
println!("No exit code");
Err(InternalError::InvalidExitCode)
value % max
}
}
}

fn native_rand_string(len: usize) -> String {
let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
let mut string = String::new();

for _ in 0..len {
string.push(chars.chars().nth(random_usize(chars.len() - 1)).unwrap());
}

string
}

#[test]
fn workload_runs_correctly() {
let entry = CodeEntry {
files: vec![],
script: vec![String::from("echo 'This is stdout' && echo 'This is stderr' >&2")],
};


let mut api = InternalApi::new(entry); // Empty code entry to avoid borrowing issues
// since the same object is used in the `run` method

let res = api.run().unwrap();

assert_eq!(res.exit_code, 0);
assert_eq!(res.stderr, "This is stderr\n");
assert_eq!(res.stdout, "This is stdout\n");
}

#[test]
fn workspace_created_sucessfully() {
let mut base_dir = PathBuf::from(WORKSPACE_PATH);
base_dir.push(native_rand_string(20));
base_dir.push("main.sh");
let path = base_dir.into_os_string().into_string().unwrap();


let entry = CodeEntry {
files: vec![
FileModel {
filename: path.clone(),
content: "#!/bin/sh\necho -n 'Some outpout'".to_string()
}
],
script: vec![path.clone()],
};

InternalApi::new(entry).create_workspace().unwrap();

assert!(Path::new(&path).exists());
}
}
10 changes: 8 additions & 2 deletions agent/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use agent_lib::{external_api::service::ExternalApi, internal_api::service::InternalApi};
use anyhow::Result;
use anyhow::{ Result, anyhow };

use log::info;
use log::{info, error};

fn main() -> Result<()> {
env_logger::init();
Expand All @@ -13,6 +13,12 @@ fn main() -> Result<()> {
let code_entry = external_api.read_from_serial()?;
let mut internal_api = InternalApi::new(code_entry);
internal_api.create_workspace()?;
let res = internal_api.run().map_err(|e| anyhow!("{:?}", e));

match res {
Err(e) => error!("Error: {:?}", e),
Ok(code) => info!("Code: {:?}", code),
}

info!("Stopping agent");
Ok(())
Expand Down

0 comments on commit dd9bf23

Please sign in to comment.