summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-06-19 14:43:48 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-06-19 14:43:48 +0200
commit1fa0de5175075a841e24925f76fc472927a5308d (patch)
tree12a4654c9c728000093605eaedc1a043a02debe0
parent512c44489c9582c40f04b8dfcdc5068c62589001 (diff)
downloadrebel-1fa0de5175075a841e24925f76fc472927a5308d.tar
rebel-1fa0de5175075a841e24925f76fc472927a5308d.zip
Collect task output to tar files
-rw-r--r--examples/foo.yml3
-rw-r--r--src/runner/runc.rs4
-rw-r--r--src/runner/runc/init.rs5
-rw-r--r--src/runner/runc/run.rs32
-rw-r--r--src/util.rs30
-rw-r--r--src/util/tar.rs23
6 files changed, 88 insertions, 9 deletions
diff --git a/examples/foo.yml b/examples/foo.yml
index e0ded83..6f60bbb 100644
--- a/examples/foo.yml
+++ b/examples/foo.yml
@@ -5,4 +5,5 @@ tasks:
run: |
ls -lha
ls -lha /proc/self/fd
- echo foo > foo
+ mkdir foo
+ echo foobar > foo/bar
diff --git a/src/runner/runc.rs b/src/runner/runc.rs
index 62a3bf1..938bab0 100644
--- a/src/runner/runc.rs
+++ b/src/runner/runc.rs
@@ -20,7 +20,7 @@ fn runner(
init_error_sender: ipc::IpcSender<init::Error>,
channel: ipc::IpcReceiver<Request>,
) -> ! {
- if let Err(error) = init::runc_unshare() {
+ if let Err(error) = init::runc_preinit() {
init_error_sender.send(error).expect("IPC send() failed");
process::exit(1);
}
@@ -37,7 +37,7 @@ fn runner(
unistd::setgid(unistd::Gid::from_raw(0)).expect("setgid()");
unistd::setgroups(&[]).expect("setgroups()");
- init::runc_initialize().unwrap();
+ init::runc_init().unwrap();
unsafe { signal::signal(signal::Signal::SIGCHLD, signal::SigHandler::SigIgn) }.unwrap();
diff --git a/src/runner/runc/init.rs b/src/runner/runc/init.rs
index e574789..f686e3e 100644
--- a/src/runner/runc/init.rs
+++ b/src/runner/runc/init.rs
@@ -51,12 +51,13 @@ impl From<Error> for io::Error {
}
}
-pub fn runc_unshare() -> Result<(), Error> {
+pub fn runc_preinit() -> Result<(), Error> {
+ DirBuilder::new().recursive(true).create("build/state")?;
sched::unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS).to_io_result()?;
Ok(())
}
-pub fn runc_initialize() -> Result<(), Error> {
+pub fn runc_init() -> Result<(), Error> {
prepare_buildtmp()?;
Ok(())
}
diff --git a/src/runner/runc/run.rs b/src/runner/runc/run.rs
index 7e9a41c..09bd875 100644
--- a/src/runner/runc/run.rs
+++ b/src/runner/runc/run.rs
@@ -1,4 +1,9 @@
-use std::{fs::DirBuilder, io, process};
+use std::{
+ fs::{DirBuilder, File},
+ io,
+ path::{Path, PathBuf},
+ process,
+};
use nix::{
mount::{self, MsFlags},
@@ -7,7 +12,11 @@ use nix::{
};
use serde::{Deserialize, Serialize};
-use crate::{types::*, unshare, util::ToIOResult};
+use crate::{
+ types::*,
+ unshare,
+ util::{self, ToIOResult},
+};
use super::spec;
@@ -59,6 +68,23 @@ fn init_task() -> Result<(), Error> {
Ok(())
}
+fn output_filename(task: TaskRef) -> PathBuf {
+ Path::new("build/state").join(format!("{}.tar", task))
+}
+
+fn collect_output(task: TaskRef, task_def: Task) -> Result<(), io::Error> {
+ // Temporarily switch to the user running Rebel to get the right
+ // owner for the tar files
+ let file = {
+ let _setegid = util::setegid(unistd::Gid::from_raw(unshare::BUILD_GID))?;
+ let _seteuid = util::seteuid(unistd::Uid::from_raw(unshare::BUILD_UID))?;
+
+ File::create(output_filename(task))?
+ };
+
+ util::tar::pack(file, "build/tmp/runc/workdir", task_def.output.iter())?.sync_all()
+}
+
pub fn handle_task(task: TaskRef, task_def: Task) -> Result<(), Error> {
init_task()?;
@@ -89,5 +115,7 @@ pub fn handle_task(task: TaskRef, task_def: Task) -> Result<(), Error> {
String::from_utf8_lossy(output.stdout.as_slice()),
);
+ collect_output(task, task_def)?;
+
Ok(())
}
diff --git a/src/util.rs b/src/util.rs
index f5bbfaa..d388a59 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -7,7 +7,7 @@ use std::{
};
use ipc_channel::ipc;
-use nix::sys::wait;
+use nix::{sys::wait, unistd};
pub trait ToIOResult<T> {
fn to_io_result(self) -> Result<T>;
@@ -68,3 +68,31 @@ impl<T> CheckDisconnect for result::Result<T, ipc::IpcError> {
}
}
}
+
+pub struct SetEUID(unistd::Uid);
+
+impl Drop for SetEUID {
+ fn drop(&mut self) {
+ unistd::seteuid(self.0).expect("failed to reset effective UID");
+ }
+}
+
+pub fn seteuid(uid: unistd::Uid) -> Result<SetEUID> {
+ let old_uid = unistd::geteuid();
+ unistd::seteuid(uid).to_io_result()?;
+ Ok(SetEUID(old_uid))
+}
+
+pub struct SetEGID(unistd::Gid);
+
+impl Drop for SetEGID {
+ fn drop(&mut self) {
+ unistd::setegid(self.0).expect("failed to reset effective GID");
+ }
+}
+
+pub fn setegid(gid: unistd::Gid) -> Result<SetEGID> {
+ let old_gid = unistd::getegid();
+ unistd::setegid(gid).to_io_result()?;
+ Ok(SetEGID(old_gid))
+}
diff --git a/src/util/tar.rs b/src/util/tar.rs
index 07ad795..885663e 100644
--- a/src/util/tar.rs
+++ b/src/util/tar.rs
@@ -1,11 +1,32 @@
use std::{
ffi::CString,
fs::DirBuilder,
- io::{self, Read},
+ io::{self, Read, Write},
os::unix::ffi::OsStrExt,
path::Path,
};
+pub fn pack<W: Write, P: AsRef<Path>, E: AsRef<Path>, I: Iterator<Item = E>>(
+ archive: W,
+ source: P,
+ entries: I,
+) -> io::Result<W> {
+ let mut ar = tar::Builder::new(archive);
+ ar.mode(tar::HeaderMode::Deterministic);
+ ar.follow_symlinks(false);
+
+ for entry in entries {
+ let path = source.as_ref().join(entry.as_ref());
+ if path.is_dir() {
+ ar.append_dir_all(entry.as_ref(), path)?;
+ } else {
+ ar.append_path_with_name(path, entry.as_ref())?;
+ }
+ }
+
+ ar.into_inner()
+}
+
pub fn unpack<R: Read, P: AsRef<Path>>(archive: R, dest: P) -> io::Result<()> {
let dest_path = dest.as_ref();