Skip to content

Commit

Permalink
wip: continue cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
cilki committed Dec 23, 2023
1 parent 15e1219 commit 3380a2f
Show file tree
Hide file tree
Showing 21 changed files with 151 additions and 112 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion goldboot-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "goldboot-macros"
version = "0.1.0"
version = "0.0.1"
edition = "2021"

[lib]
Expand Down
1 change: 1 addition & 0 deletions goldboot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ gdk4 = { version = "0.7.3", optional = true }
gdk-pixbuf = { version = "0.18.3", optional = true }
glib-macros = { version = "0.18.3", optional = true }
goldboot-image = { path="../goldboot-image", version = "0.0.1" }
goldboot-macros = { path="../goldboot-macros", version = "0.0.1" }
gtk4 = { version = "0.7.3", optional = true }
hex = "0.4.3"
indicatif = "0.17.7"
Expand Down
11 changes: 7 additions & 4 deletions goldboot/src/cli/cmd/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::foundry::{Foundry, FoundryConfig};
use anyhow::anyhow;
use anyhow::Result;
use log::debug;
use validator::Validate;
Expand All @@ -12,12 +13,14 @@ pub fn run(cmd: super::Commands) -> Result<()> {
output,
path,
} => {
let config_path =
FoundryConfig::from_dir(path).ok_or(Err("No goldboot config found"))?;
let config_path = FoundryConfig::from_dir(path.unwrap_or(".".to_string()))
.ok_or_else(|| anyhow!("No config found"))?;
debug!("Loading config from {}", config_path);

// Load config from current directory
let mut foundry: Foundry = config_path.load()?;
foundry.debug = debug;
foundry.record = record;
debug!("Loaded: {:#?}", &foundry);

// Include the encryption password if provided
Expand All @@ -36,8 +39,8 @@ pub fn run(cmd: super::Commands) -> Result<()> {
foundry.validate()?;

// Run the build finally
let mut job = foundry.run(record, debug);
job.run(output.to_owned())
foundry.run(output)?;
Ok(())
}
_ => panic!(),
}
Expand Down
29 changes: 15 additions & 14 deletions goldboot/src/cli/cmd/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,23 @@ pub fn run(cmd: super::Commands) -> Result<()> {
match cmd {
super::Commands::Init {
name,
template,
mold,
mimic_hardware,
} => {
let config_path =
FoundryConfig::from_dir(".").unwrap_or(FoundryConfig::Ron("./goldboot.ron"));
FoundryConfig::from_dir(".").unwrap_or(FoundryConfig::Ron("./goldboot.ron".into()));

// Build a new default config that we'll override
let mut config = Foundry::default();
let mut foundry = Foundry::default();

if template.len() > 0 {
if mold.len() > 0 {
// If a mold name was given, use the default
if let Some(name) = name {
config.name = name;
foundry.name = name;
} else {
// Set name equal to directory name
if let Some(name) = std::env::current_dir()?.file_name() {
config.name = name.to_str().unwrap().to_string();
foundry.name = name.to_str().unwrap().to_string();
}
}

Expand All @@ -58,20 +59,20 @@ pub fn run(cmd: super::Commands) -> Result<()> {
// Generate QEMU flags for this hardware
//config.qemuargs = generate_qemuargs()?;
} else {
// Begin interactive config
// If no mold was given, begin interactive config
print_banner();

let theme = ColorfulTheme {
values_style: Style::new().yellow().dim(),
..ColorfulTheme::default()
};

println!("Get ready to build a new image configuration!");
println!("Get ready to create a new image configuration!");
println!("(it can be further edited later)");
println!();

// Prompt image name
config.name = Input::with_theme(&theme)
foundry.name = Input::with_theme(&theme)
.with_prompt("Enter image name")
.default(
std::env::current_dir()?
Expand All @@ -92,14 +93,14 @@ pub fn run(cmd: super::Commands) -> Result<()> {
.items(&architectures)
.interact()?;

config.arch = architectures[choice_index];
foundry.arch = architectures[choice_index];
}

loop {
// Find molds suitable for the architecture
let molds: Vec<ImageMold> = ImageMold::iter()
.filter(|mold| mold.architectures().contains(&config.arch))
.filter(|mold| config.templates.len() == 0 || mold.alloy())
.filter(|mold| mold.architectures().contains(&foundry.arch))
.filter(|mold| foundry.molds().len() == 0 || mold.alloy())
.collect();

let choice_index = Select::with_theme(&theme)
Expand All @@ -108,7 +109,7 @@ pub fn run(cmd: super::Commands) -> Result<()> {
.interact()?;

let mold = &molds[choice_index];
config.templates.push(mold);
// foundry.templates.push(mold);

if !mold.alloy()
|| !Confirm::with_theme(&theme)
Expand All @@ -121,7 +122,7 @@ pub fn run(cmd: super::Commands) -> Result<()> {
}

// Finally write out the config
config_path.write(&config)?;
config_path.write(&foundry)?;
Ok(())
}
_ => panic!(),
Expand Down
6 changes: 4 additions & 2 deletions goldboot/src/cli/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ pub enum Commands {
#[clap(long)]
name: Option<String>,

/// A base template (which can be found with --list-templates)
/// A base mold that can be customized further
#[clap(long)]
template: Vec<String>, // TODO set to ImageMold?
mold: Vec<String>,

// #[clap(long, num_args = 0)]
// list: bool,
/// Attempt to copy the configuration of the current hardware as closely
/// as possible
#[clap(long, num_args = 0)]
Expand Down
12 changes: 10 additions & 2 deletions goldboot/src/foundry/fabricators/ansible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use serde::{Deserialize, Serialize};
use std::{error::Error, path::Path, process::Command};
use validator::Validate;

use super::Fabricate;

/// Runs an Ansible playbook on the image remotely.
#[derive(Clone, Serialize, Deserialize, Validate, Debug)]
pub struct Ansible {
Expand Down Expand Up @@ -47,14 +49,20 @@ impl Ansible {
}
}

impl Fabricate for Ansible {
fn run(&self, ssh: &mut SshConnection) -> Result<()> {
todo!()
}
}

impl Prompt for Ansible {
fn prompt(&mut self, _: &Foundry, theme: Box<dyn Theme>) -> Result<()> {
self.playbook = dialoguer::Input::with_theme(&theme)
self.playbook = dialoguer::Input::with_theme(&*theme)
.with_prompt("Enter the playbook path relative to the current directory")
.interact()?;

if !Path::new(&self.playbook).exists() {
if !dialoguer::Confirm::with_theme(&theme)
if !dialoguer::Confirm::with_theme(&*theme)
.with_prompt("The path does not exist. Add anyway?")
.interact()?
{
Expand Down
4 changes: 2 additions & 2 deletions goldboot/src/foundry/fabricators/exe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ impl Fabricate for HostExecutable {

impl Prompt for HostExecutable {
fn prompt(&mut self, _: &Foundry, theme: Box<dyn Theme>) -> Result<()> {
self.path = dialoguer::Input::with_theme(&theme)
self.path = dialoguer::Input::with_theme(&*theme)
.with_prompt("Enter the script path relative to the current directory")
.interact()?;

if !Path::new(&self.path).exists() {
if !dialoguer::Confirm::with_theme(&theme)
if !dialoguer::Confirm::with_theme(&*theme)
.with_prompt("The path does not exist. Add anyway?")
.interact()?
{
Expand Down
2 changes: 2 additions & 0 deletions goldboot/src/foundry/fabricators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::foundry::ssh::SshConnection;
use ansible::Ansible;
use anyhow::Result;
use enum_dispatch::enum_dispatch;
use serde::{Deserialize, Serialize};

pub mod ansible;
pub mod exe;
Expand All @@ -20,6 +21,7 @@ pub trait Fabricate {
}

#[enum_dispatch]
#[derive(Clone, Serialize, Deserialize, Debug)]
pub enum Fabricator {
Ansible,
}
58 changes: 38 additions & 20 deletions goldboot/src/foundry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use rand::Rng;
use ron::ser::PrettyConfig;
use serde::{Deserialize, Serialize};
use std::{
error::Error,
fmt::Display,
path::{Path, PathBuf},
thread,
Expand Down Expand Up @@ -102,7 +101,7 @@ impl Foundry {
// Unpack included firmware
let ovmf_path = tmp.path().join("OVMF.fd").to_string_lossy().to_string();

crate::ovmf::write_to(&self.config.arch, &ovmf_path)?;
// crate::ovmf::write_to(&self.config.arch, &ovmf_path)?;

FoundryWorker {
tmp,
Expand All @@ -118,17 +117,23 @@ impl Foundry {
}
}

pub fn molds(&self) -> Vec<&ImageMold> {
if let Some(mold) = &self.mold {
vec![mold]
} else {
todo!()
}
}

/// Run the entire build process. If no output file is given, the image is
/// moved into the image library.
pub fn run(&mut self, output: Option<String>) -> Result<()> {
self.start_time = Some(SystemTime::now());

// Track the workers
let mut workers = Vec::new();

// If we're in debug mode, run workers sequentially
if self.debug {
for template in self.config.templates.into_iter() {
for mold in self.molds() {
let worker = self.new_worker(template)?;

Check failure on line 137 in goldboot/src/foundry/mod.rs

View workflow job for this annotation

GitHub Actions / Build Windows

cannot find value `template` in this scope

Check failure on line 137 in goldboot/src/foundry/mod.rs

View workflow job for this annotation

GitHub Actions / Build Linux

cannot find value `template` in this scope

Check failure on line 137 in goldboot/src/foundry/mod.rs

View workflow job for this annotation

GitHub Actions / Build macOS

cannot find value `template` in this scope
worker.run()?;
workers.push(worker);
Expand All @@ -138,7 +143,7 @@ impl Foundry {
else {
let mut handles = Vec::new();

for template in self.config.templates.into_iter() {
for mold in self.molds() {
let worker = self.new_worker(template)?;

Check failure on line 147 in goldboot/src/foundry/mod.rs

View workflow job for this annotation

GitHub Actions / Build Windows

cannot find value `template` in this scope

Check failure on line 147 in goldboot/src/foundry/mod.rs

View workflow job for this annotation

GitHub Actions / Build Linux

cannot find value `template` in this scope

Check failure on line 147 in goldboot/src/foundry/mod.rs

View workflow job for this annotation

GitHub Actions / Build macOS

cannot find value `template` in this scope
handles.push(thread::spawn(move || {
worker.run().unwrap();
Expand Down Expand Up @@ -171,12 +176,6 @@ impl Foundry {
ImageLibrary::add(&self.image_path)?;
}

info!(
"Build completed in: {:?}",
self.start_time.unwrap().elapsed()?
);
self.end_time = Some(SystemTime::now());

Ok(())
}
}
Expand Down Expand Up @@ -206,6 +205,7 @@ pub struct FoundryWorker {
impl FoundryWorker {
/// Run the template build.
pub fn run(&self) -> Result<()> {
self.start_time = Some(SystemTime::now());
debug!(
"Allocating new {} image: {}",
self.template.general().storage_size,
Expand All @@ -226,6 +226,12 @@ impl FoundryWorker {
// ));

self.template.build(&self)?;
info!(
"Build completed in: {:?}",
self.start_time.unwrap().elapsed()?
);
self.end_time = Some(SystemTime::now());

Ok(())
}
}
Expand All @@ -242,7 +248,7 @@ pub enum FoundryConfig {
impl FoundryConfig {
/// Check for a foundry configuration file in the given directory.
pub fn from_dir(path: impl AsRef<Path>) -> Option<FoundryConfig> {
path = path.as_ref();
let path = path.as_ref();

if path.join("goldboot.json").exists() {
Some(FoundryConfig::Json(path.join("goldboot.json")))
Expand All @@ -261,12 +267,12 @@ impl FoundryConfig {

/// Read the configuration file into a new [`Foundry`].
pub fn load(&self) -> Result<Foundry> {
match &self {
Self::Json(path) => serde_json::from_slice(std::fs::read(path)),
Self::Ron(path) => ron::de::from_bytes(std::fs::read(path)),
Self::Toml(path) => toml::from_str(String::from_utf8(std::fs::read(path))?.as_str()),
Self::Yaml(path) => serde_yaml::from_slice(std::fs::read(path)),
}
Ok(match &self {
Self::Json(path) => serde_json::from_slice(&std::fs::read(path)?)?,
Self::Ron(path) => ron::de::from_bytes(&std::fs::read(path)?)?,
Self::Toml(path) => toml::from_str(String::from_utf8(std::fs::read(path)?)?.as_str())?,
Self::Yaml(path) => serde_yaml::from_slice(&std::fs::read(path)?)?,
})
}

/// Write a [`Foundry`] to a configuration file.
Expand All @@ -279,6 +285,18 @@ impl FoundryConfig {
),
Self::Toml(path) => std::fs::write(path, toml::to_string_pretty(foundry)?.into_bytes()),
Self::Yaml(path) => std::fs::write(path, serde_yaml::to_string(foundry)?.into_bytes()),
}
}?;
Ok(())
}
}

impl Display for FoundryConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
FoundryConfig::Json(path) => &path.to_string_lossy(),
FoundryConfig::Ron(path) => &path.to_string_lossy(),
FoundryConfig::Toml(path) => &path.to_string_lossy(),
FoundryConfig::Yaml(path) => &path.to_string_lossy(),
})
}
}
Loading

0 comments on commit 3380a2f

Please sign in to comment.