Skip to content

Commit

Permalink
wip: add enum dispatch for fabricators too
Browse files Browse the repository at this point in the history
  • Loading branch information
cilki committed Nov 26, 2023
1 parent 82b5abf commit 4648e4f
Show file tree
Hide file tree
Showing 16 changed files with 280 additions and 218 deletions.
26 changes: 24 additions & 2 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion goldboot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ clap = { version = "4.4.7", features = ["derive"] }
console = "0.15.7"
dialoguer = "0.11.0"
env_logger = "0"
fossable = "0.1.0"
fossable = "0.1.2"
gdk4 = { version = "0.7.3", optional = true }
gdk-pixbuf = { version = "0.18.3", optional = true }
glib-macros = { version = "0.18.3", optional = true }
Expand Down Expand Up @@ -45,6 +45,9 @@ vnc = "0.4.0"
whoami = "1.4.1"
zstd = "0.13.0"
enum_dispatch = "0.3.12"
serde_json = "1.0.108"
toml = "0.8.8"
serde_yaml = "0.9.27"

[dev-dependencies]
test-env-log = "0"
Expand Down
30 changes: 9 additions & 21 deletions goldboot/src/cli/cmd/build.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,39 @@
use console::Style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
use crate::foundry::{Foundry, FoundryConfig};
use log::debug;
use std::{error::Error, path::Path};
use std::error::Error;
use validator::Validate;

use crate::foundry::Foundry;

pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
match cmd {
super::Commands::Build {
super::Commands::Cast {
record,
debug,
read_password,
output,
path,
} => {
let context_path = if let Some(path) = path.to_owned() {
path.as_str()
} else {
if Path::new("./goldboot.yaml").exists() {
"./goldboot.yaml"
} else if Path::new("./goldboot.yml").exists() {
"./goldboot.yml"
} else {
todo!()
}
};
let config_path =
FoundryConfig::from_dir(path).ok_or(Err("No goldboot config found"))?;
debug!("Loading config from {}", config_path);

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

// Include the encryption password if provided
if read_password {
print!("Enter password: ");
let mut password = String::new();
std::io::stdin().read_line(&mut password)?;
config.password = Some(password);
// config.password = Some(password);
} else if let Ok(password) = std::env::var("GOLDBOOT_PASSWORD") {
// Wipe out the value since we no longer need it
std::env::set_var("GOLDBOOT_PASSWORD", "");
config.password = Some(password);
// config.password = Some(password);
}

// Fully verify config before proceeding
config.validate()?;
foundry.validate()?;

// Run the build finally
let mut job = BuildJob::new(config, record, debug);

Check failure on line 39 in goldboot/src/cli/cmd/build.rs

View workflow job for this annotation

GitHub Actions / Build Windows

failed to resolve: use of undeclared type `BuildJob`

Check failure on line 39 in goldboot/src/cli/cmd/build.rs

View workflow job for this annotation

GitHub Actions / Build Windows

cannot find value `config` in this scope

Check failure on line 39 in goldboot/src/cli/cmd/build.rs

View workflow job for this annotation

GitHub Actions / Build macOS

failed to resolve: use of undeclared type `BuildJob`

Check failure on line 39 in goldboot/src/cli/cmd/build.rs

View workflow job for this annotation

GitHub Actions / Build macOS

cannot find value `config` in this scope

Check failure on line 39 in goldboot/src/cli/cmd/build.rs

View workflow job for this annotation

GitHub Actions / Build Linux

failed to resolve: use of undeclared type `BuildJob`

Check failure on line 39 in goldboot/src/cli/cmd/build.rs

View workflow job for this annotation

GitHub Actions / Build Linux

cannot find value `config` in this scope
Expand Down
8 changes: 2 additions & 6 deletions goldboot/src/cli/cmd/image.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
use crate::{
cmd::{Commands, ImageCommands},
library::ImageLibrary,
};
use chrono::TimeZone;
use console::Style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
Expand All @@ -11,7 +7,7 @@ use ubyte::ToByteUnit;
pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
match cmd {
super::Commands::Image { command } => match &command {
ImageCommands::List {} => {
super::ImageCommands::List {} => {
let images = ImageLibrary::load()?;

Check failure on line 11 in goldboot/src/cli/cmd/image.rs

View workflow job for this annotation

GitHub Actions / Build Windows

failed to resolve: use of undeclared type `ImageLibrary`

Check failure on line 11 in goldboot/src/cli/cmd/image.rs

View workflow job for this annotation

GitHub Actions / Build macOS

failed to resolve: use of undeclared type `ImageLibrary`

Check failure on line 11 in goldboot/src/cli/cmd/image.rs

View workflow job for this annotation

GitHub Actions / Build Linux

failed to resolve: use of undeclared type `ImageLibrary`

println!("Image Name Image Size Build Date Image ID Description");
Expand All @@ -29,7 +25,7 @@ pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
}
Ok(())
}
ImageCommands::Info { image } => {
super::ImageCommands::Info { image } => {
if let Some(image) = image {
let image = ImageLibrary::find_by_id(image)?;

Check failure on line 30 in goldboot/src/cli/cmd/image.rs

View workflow job for this annotation

GitHub Actions / Build Windows

failed to resolve: use of undeclared type `ImageLibrary`

Check failure on line 30 in goldboot/src/cli/cmd/image.rs

View workflow job for this annotation

GitHub Actions / Build macOS

failed to resolve: use of undeclared type `ImageLibrary`

Check failure on line 30 in goldboot/src/cli/cmd/image.rs

View workflow job for this annotation

GitHub Actions / Build Linux

failed to resolve: use of undeclared type `ImageLibrary`
// TODO
Expand Down
64 changes: 31 additions & 33 deletions goldboot/src/cli/cmd/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use simple_error::bail;
use std::{error::Error, path::Path};
use strum::IntoEnumIterator;

use crate::foundry::{mold::builtins::ImageMold, Foundry, FoundryConfig};

fn print_banner() {
if console::colors_enabled() {
let style = Style::new().yellow();
Expand All @@ -24,14 +26,11 @@ pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
template,
mimic_hardware,
} => {
let config_path = Path::new("goldboot.yml");

if config_path.exists() {
bail!("This directory has already been initialized. Delete goldboot.yml to reinitialize.");
}
let config_path =
FoundryConfig::from_dir(".").unwrap_or(FoundryConfig::Ron("./goldboot.ron"));

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

if template.len() > 0 {
if let Some(name) = name {
Expand All @@ -44,19 +43,19 @@ pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
}

// Add default templates
for template_id in template {
if let Some(id) = Template::iter()
.filter(|id| id.to_string() == template_id)
.next()
{
config.templates.push(id.default());
} else {
bail!("Template not found");
}
}

// Generate QEMU flags for this hardware
//config.qemuargs = generate_qemuargs()?;
// for template_id in template {
// if let Some(id) = Template::iter()
// .filter(|id| id.to_string() == template_id)
// .next()
// {
// config.templates.push(id.default());
// } else {
// bail!("Template not found");
// }
// }

// Generate QEMU flags for this hardware
//config.qemuargs = generate_qemuargs()?;
} else {
// Begin interactive config
print_banner();
Expand Down Expand Up @@ -86,32 +85,31 @@ pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
// Prompt image architecture
{
let architectures: Vec<ImageArch> = ImageArch::iter().collect();
let arch_index = Select::with_theme(&theme)
let choice_index = Select::with_theme(&theme)
.with_prompt("Choose image architecture")
.default(0)
.items(&architectures)
.interact()?;

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

loop {
// Find templates suitable for the architecture
let templates: Vec<TemplateMetadata> = TemplateMetadata::all()
.into_iter()
.filter(|metadata| metadata.architectures.contains(&config.arch))
.filter(|metadata| config.templates.len() == 0 || metadata.multiboot)
// 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())
.collect();

let template_index = Select::with_theme(&theme)
.with_prompt("Choose image template")
.items(&templates)
let choice_index = Select::with_theme(&theme)
.with_prompt("Choose image mold")
.items(&molds)
.interact()?;

let template_metadata = &templates[template_index];
config.templates.push(template_metadata.default());
let mold = &molds[choice_index];
config.templates.push(mold);

if !template_metadata.multiboot
if !mold.alloy()
|| !Confirm::with_theme(&theme)
.with_prompt("Do you want to add another OS for multibooting?")
.interact()?
Expand All @@ -122,7 +120,7 @@ pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
}

// Finally write out the config
std::fs::write(config_path, ron::to_string(&config)?)?;
config_path.write(&config)?;
Ok(())
}
_ => panic!(),
Expand Down
10 changes: 5 additions & 5 deletions goldboot/src/cli/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pub mod write;

#[derive(clap::Subcommand, Debug)]
pub enum Commands {
/// Build a new image
Build {
/// Cast (build) a new image
Cast {
/// Save a screenshot to ./screenshots after each boot command for
/// debugging
#[clap(long, num_args = 0)]
Expand All @@ -25,9 +25,9 @@ pub enum Commands {
#[clap(long)]
output: Option<String>,

/// The config file path (default: ./goldboot.json)
/// The context directory (containing a goldboot config file)
#[clap(long)]
config: Option<String>,
path: Option<String>,
},

/// Manage local images
Expand Down Expand Up @@ -59,7 +59,7 @@ pub enum Commands {

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

/// Attempt to copy the configuration of the current hardware as closely
/// as possible
Expand Down
2 changes: 2 additions & 0 deletions goldboot/src/cli/cmd/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use console::Style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
use std::{error::Error, path::Path};

use crate::library::ImageLibrary;

pub fn run(cmd: super::Commands) -> Result<(), Box<dyn Error>> {
match cmd {
super::Commands::Write {
Expand Down
6 changes: 3 additions & 3 deletions goldboot/src/foundry/fabricators/ansible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ use validator::Validate;

/// Runs an Ansible playbook on the image remotely.
#[derive(Clone, Serialize, Deserialize, Validate, Debug)]
pub struct AnsibleFabricator {
pub struct Ansible {
/// The playbook file
pub playbook: String,

/// The inventory file
pub inventory: Option<String>,
}

impl AnsibleFabricator {
impl Ansible {
pub fn run(&self, ssh: &mut SshConnection) -> Result<(), Box<dyn Error>> {
info!("Running ansible provisioner");

Expand Down Expand Up @@ -44,7 +44,7 @@ impl AnsibleFabricator {
}
}

impl Prompt for AnsibleFabricator {
impl Prompt for Ansible {
fn prompt(
&mut self,
config: &BuildConfig,

Check failure on line 50 in goldboot/src/foundry/fabricators/ansible.rs

View workflow job for this annotation

GitHub Actions / Build Windows

cannot find type `BuildConfig` in this scope

Check failure on line 50 in goldboot/src/foundry/fabricators/ansible.rs

View workflow job for this annotation

GitHub Actions / Build macOS

cannot find type `BuildConfig` in this scope

Check failure on line 50 in goldboot/src/foundry/fabricators/ansible.rs

View workflow job for this annotation

GitHub Actions / Build Linux

cannot find type `BuildConfig` in this scope
Expand Down
17 changes: 8 additions & 9 deletions goldboot/src/foundry/fabricators/exe.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
use std::{error::Error, path::Path};
use super::Fabricate;
use crate::{cli::prompt::Prompt, foundry::ssh::SshConnection};
use log::info;
use serde::{Deserialize, Serialize};
use simple_error::bail;
use std::{error::Error, path::Path};
use validator::Validate;
use super::Fabricator;

/// Runs an executable file.
#[derive(Clone, Serialize, Deserialize, Validate, Debug)]
pub struct ExecutableFabricator {
pub struct HostExecutable {
/// The path to the executable
pub path: String,
}

impl ExecutableFabricator {
pub fn run(&self, ssh: &mut SshConnection) -> Result<(), Box<dyn Error>> {
impl Fabricate for HostExecutable {
fn run(&self, ssh: &mut SshConnection) -> Result<(), Box<dyn Error>> {
info!("Running executable");

if ssh.upload_exec(&std::fs::read(self.path.clone())?, vec![])? != 0 {
if ssh.upload_exec(&std::fs::read(&self.path)?, vec![])? != 0 {
bail!("Executable failed");
}
Ok(())
}
}

impl Prompt for ExecutableFabricator {
impl Prompt for HostExecutable {
fn prompt(
&mut self,
config: &BuildConfig,

Check failure on line 30 in goldboot/src/foundry/fabricators/exe.rs

View workflow job for this annotation

GitHub Actions / Build Windows

cannot find type `BuildConfig` in this scope

Check failure on line 30 in goldboot/src/foundry/fabricators/exe.rs

View workflow job for this annotation

GitHub Actions / Build macOS

cannot find type `BuildConfig` in this scope

Check failure on line 30 in goldboot/src/foundry/fabricators/exe.rs

View workflow job for this annotation

GitHub Actions / Build Linux

cannot find type `BuildConfig` in this scope
Expand All @@ -46,5 +47,3 @@ impl Prompt for ExecutableFabricator {
Ok(())
}
}

impl Fabricator for ExecutableFabricator;
Loading

0 comments on commit 4648e4f

Please sign in to comment.