Add shared_directories preset parameter (#35)

This commit is contained in:
James McMurray
2020-03-26 19:57:46 +01:00
committed by GitHub
parent 14347710ce
commit bc9969a0db
6 changed files with 100 additions and 12 deletions

View File

@@ -25,7 +25,7 @@ use std::process::{exit, Command as ProcessCommand};
use std::thread;
use std::time::Duration;
use storage::EncryptedDevice;
use storage::{BlockDevice, Filesystem, FilesystemType, LoopDevice};
use storage::{BlockDevice, Filesystem, FilesystemType, LoopDevice, MountStack};
use structopt::StructOpt;
use tempfile::tempdir;
use tool::Tool;
@@ -264,10 +264,33 @@ fn create(command: args::CreateCommand) -> Result<(), Error> {
}
for script in presets.scripts {
let mut bind_mount_stack = MountStack::new();
if let Some(shared_dirs) = &script.shared_dirs {
for dir in shared_dirs {
// Create shared directories mount points inside chroot
std::fs::create_dir_all(
mount_point
.path()
.join(PathBuf::from("shared_dirs/"))
.join(dir.file_name().unwrap()),
)
.context(ErrorKind::PresetScript)?;
// Bind mount shared directories
let target = mount_point
.path()
.join(PathBuf::from("shared_dirs/"))
.join(dir.file_name().unwrap());
bind_mount_stack
.bind_mount(dir.clone(), target, None)
.context(ErrorKind::Mounting)?;
}
}
let mut script_file =
tempfile::NamedTempFile::new_in(mount_point.path()).context(ErrorKind::PresetScript)?;
script_file
.write_all(script.as_bytes())
.write_all(script.script_text.as_bytes())
.and_then(|_| script_file.as_file_mut().metadata())
.and_then(|metadata| {
let mut permissions = metadata.permissions();

View File

@@ -12,6 +12,7 @@ struct Preset {
packages: Option<Vec<String>>,
script: Option<String>,
environment_variables: Option<Vec<String>>,
shared_directories: Option<Vec<PathBuf>>,
}
fn visit_dirs(dir: &Path, filevec: &mut Vec<PathBuf>) -> Result<(), io::Error> {
@@ -22,7 +23,9 @@ fn visit_dirs(dir: &Path, filevec: &mut Vec<PathBuf>) -> Result<(), io::Error> {
if path.is_dir() {
visit_dirs(&path, filevec)?;
} else {
filevec.push(entry.path());
if entry.path().extension() == Some(&std::ffi::OsString::from("toml")) {
filevec.push(entry.path());
}
}
}
}
@@ -40,9 +43,10 @@ impl Preset {
fn process(
&self,
packages: &mut HashSet<String>,
scripts: &mut Vec<String>,
scripts: &mut Vec<Script>,
environment_variables: &mut HashSet<String>,
) {
path: &PathBuf,
) -> Result<(), ErrorKind> {
if let Some(preset_packages) = &self.packages {
packages.extend(preset_packages.clone());
}
@@ -51,19 +55,52 @@ impl Preset {
environment_variables.extend(preset_environment_variables.clone());
}
scripts.extend(self.script.clone());
if let Some(script_text) = &self.script {
scripts.push(Script {
script_text: script_text.clone(),
shared_dirs: self
.shared_directories
.clone()
.map(|x| {
// Convert directories to absolute paths
// If any shared directory is not a directory then throw an error
x.iter()
.cloned()
.map(|y| {
let full_path = path.parent().unwrap().join(&y);
if full_path.is_dir() {
Ok(full_path)
} else {
Err(ErrorKind::Preset(format!(
"Preset: {} - shared directory: {} is not directory",
path.display(),
y.display()
)))
}
})
.collect::<Result<Vec<_>, ErrorKind>>()
})
.map_or(Ok(None), |r| r.map(Some))?,
});
}
Ok(())
}
}
pub struct Script {
pub script_text: String,
pub shared_dirs: Option<Vec<PathBuf>>,
}
pub struct PresetsCollection {
pub packages: HashSet<String>,
pub scripts: Vec<String>,
pub scripts: Vec<Script>,
}
impl PresetsCollection {
pub fn load(list: &[PathBuf]) -> Result<Self, Error> {
let mut packages = HashSet::new();
let mut scripts = Vec::new();
let mut scripts: Vec<Script> = Vec::new();
let mut environment_variables = HashSet::new();
for preset in list {
@@ -83,17 +120,18 @@ impl PresetsCollection {
&mut packages,
&mut scripts,
&mut environment_variables,
);
&path,
)?;
}
} else {
Preset::load(&preset)?.process(
&mut packages,
&mut scripts,
&mut environment_variables,
);
&preset,
)?;
}
}
let missing_envrionments: Vec<String> = environment_variables
.into_iter()
.filter(|var| env::var(var).is_err())

View File

@@ -38,6 +38,24 @@ impl<'a> MountStack<'a> {
Ok(())
}
pub fn bind_mount(
&mut self,
source: PathBuf,
target: PathBuf,
options: Option<&str>,
) -> nix::Result<()> {
debug!("Mounting {:?} to {:?}", source, target);
mount::<_, _, str, _>(
Some(&source),
&target,
None,
MsFlags::MS_BIND | MsFlags::MS_NOATIME, // Read-only flag has no effect for bind mounts
options,
)?;
self.targets.push(target);
Ok(())
}
fn _umount(&mut self) -> Result<(), Error> {
let mut result = Ok(());