summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2023-08-19 09:03:26 +0300
committerLars Wirzenius <liw@liw.fi>2023-08-19 09:45:45 +0300
commitb46384d45225b58b1efc5ca195560baa7b8369c7 (patch)
treea8facc1c79171b80d8ec81207ebdc130d6715366
parent0bd2cf284755610a52b081368756170c69835868 (diff)
downloadambient-run-b46384d45225b58b1efc5ca195560baa7b8369c7.tar.gz
feat: per-user and per-project configurations can specify a VM image
The per-project configuration setting overrides the per-user setting. Sponsored-by: author
-rw-r--r--ambient-run.md5
-rw-r--r--src/bin/ambient-run.rs4
-rw-r--r--src/config.rs7
-rw-r--r--src/project.rs40
4 files changed, 44 insertions, 12 deletions
diff --git a/ambient-run.md b/ambient-run.md
index 57b47d9..e290364 100644
--- a/ambient-run.md
+++ b/ambient-run.md
@@ -122,14 +122,17 @@ then stdout, as YAML, matches file full-config.yaml
~~~
~~~{#default.yaml .file .yaml}
+image: /my/image.qcow2
max_cpus: 4
~~~
~~~{#extra.yaml .file .yaml}
+image: /other/image.qcow2
max_cpus: 8
~~~
~~~{#full-config.yaml .file .yaml}
+image: /other/image.qcow2
max_cpus: 8
~~~
@@ -146,6 +149,7 @@ _Stakeholder:_ Lars
~~~scenario
given an installed ambient-run
+given file .config/ambient-run/config.yaml from default.yaml
given file project.yaml
when I run ambient-run project project.yaml
then stdout, as YAML, matches file full-project.yaml
@@ -160,6 +164,7 @@ shell: |
source: .
shell: |
cargo test
+image: /my/image.qcow2
~~~
### Show per-build configuration
diff --git a/src/bin/ambient-run.rs b/src/bin/ambient-run.rs
index d81c96a..da74b15 100644
--- a/src/bin/ambient-run.rs
+++ b/src/bin/ambient-run.rs
@@ -97,8 +97,8 @@ struct ProjectCommand {
}
impl ProjectCommand {
- fn run(&self, _global: &Args, _config: &Config) -> Result<(), AmbientRunError> {
- let project = Project::load(&self.filename)?;
+ fn run(&self, _global: &Args, config: &Config) -> Result<(), AmbientRunError> {
+ let project = Project::load(&self.filename, config)?;
println!("{}", project.as_yaml()?);
Ok(())
}
diff --git a/src/config.rs b/src/config.rs
index f87b347..28e6e96 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -13,6 +13,9 @@ const CONFIG: &str = "config.yaml";
pub struct Config {
/// Maximum number of virtual CPUs the build VM may have.
pub max_cpus: usize,
+
+ /// Path to base image to use. This can also be specified by the project.
+ pub image: Option<PathBuf>,
}
impl Config {
@@ -40,6 +43,9 @@ impl Config {
if let Some(n) = snippet.max_cpus {
self.max_cpus = n;
}
+ if snippet.image.is_some() {
+ self.image = snippet.image;
+ }
Ok(())
}
@@ -53,6 +59,7 @@ impl Config {
#[serde(deny_unknown_fields)]
struct ConfigSnippet {
max_cpus: Option<usize>,
+ image: Option<PathBuf>,
}
/// Return canonical path name to default configuration file.
diff --git a/src/project.rs b/src/project.rs
index a9eb5dc..b672867 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -1,5 +1,6 @@
//! ambient-run project build information handling.
+use crate::config::Config;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
@@ -8,13 +9,30 @@ use std::path::{Path, PathBuf};
pub struct Project {
source: PathBuf,
shell: String,
+ image: PathBuf,
}
impl Project {
/// Load build instructions from named file.
- pub fn load(filename: &Path) -> Result<Self, ProjectError> {
- let mut project = Self::default();
+ pub fn load(filename: &Path, config: &Config) -> Result<Self, ProjectError> {
+ let no_image = PathBuf::from("/no/image/specified");
+ let image = if let Some(image) = &config.image {
+ image.to_path_buf()
+ } else {
+ no_image.clone()
+ };
+ let mut project = Self {
+ source: PathBuf::from("."),
+ shell: "".into(),
+ image,
+ };
project.add_from(filename)?;
+ if project.shell.is_empty() {
+ return Err(ProjectError::NoShell);
+ }
+ if project.image == no_image {
+ return Err(ProjectError::NoImage);
+ }
Ok(project)
}
@@ -33,6 +51,9 @@ impl Project {
if let Some(x) = snippet.shell {
self.shell = x;
}
+ if let Some(x) = snippet.image {
+ self.image = x;
+ }
Ok(())
}
@@ -42,19 +63,12 @@ impl Project {
}
}
-impl Default for Project {
- fn default() -> Self {
- Self {
- source: PathBuf::from("."),
- shell: "echo do nothing by default\n".into(),
- }
- }
-}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct ProjectSnippet {
source: Option<PathBuf>,
shell: Option<String>,
+ image: Option<PathBuf>,
}
/// Possible errors from configuration file handling.
@@ -69,4 +83,10 @@ pub enum ProjectError {
#[error("failed to serialize project build instructions as YAML")]
AsYaml(#[source] serde_yaml::Error),
+
+ #[error("no shell commands for building specified by project")]
+ NoShell,
+
+ #[error("no image specified by project or config")]
+ NoImage,
}