Skip to content

Commit

Permalink
Merge branch '40-refactor-clean-standard-implementation-of-cli-modules'
Browse files Browse the repository at this point in the history
  • Loading branch information
gmpinder committed Feb 6, 2024
2 parents b70da3a + 96b680e commit 245ddf0
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 166 deletions.
72 changes: 2 additions & 70 deletions src/commands/bug_report.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
use crate::module_recipe::{Module, ModuleExt, Recipe};
use crate::module_recipe::Recipe;
use crate::shadow;

use anyhow::Result;
use askama::Template;
use clap::Args;
use clap_complete::Shell;
use format_serde_error::SerdeError;
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
use log::{debug, error, trace};
use requestty::question::{completions, Completions};
use std::borrow::Cow;
use std::fs;
use std::path::PathBuf;
use std::time::Duration;
use typed_builder::TypedBuilder;

Expand Down Expand Up @@ -344,9 +340,7 @@ fn generate_github_issue(
environment: &Environment,
recipe: &Option<Recipe>,
) -> anyhow::Result<String> {
let recipe = recipe
.as_ref()
.map_or_else(Default::default, |r| print_full_recipe(r));
let recipe = serde_yaml::to_string(recipe)?;

let github_template = GithubIssueTemplate::builder()
.bb_version(shadow::PKG_VERSION)
Expand Down Expand Up @@ -381,68 +375,6 @@ fn make_github_issue_link(body: &str) -> String {
.collect()
}

fn get_module_from_file(file_name: &str) -> Result<ModuleExt> {
let file_path = PathBuf::from("config").join(file_name);
let file_path = if file_path.is_absolute() {
file_path
} else {
std::env::current_dir()?.join(file_path)
};

let file = fs::read_to_string(file_path.clone())?;

serde_yaml::from_str::<ModuleExt>(&file).map_or_else(
|err| -> Result<ModuleExt> {
error!(
"Failed to parse module from {}: {}",
file_path.display(),
SerdeError::new(file.to_owned(), err).to_string()
);

let module =
serde_yaml::from_str::<Module>(&file).map_err(|err| SerdeError::new(file, err))?;
Ok(ModuleExt::builder().modules(vec![module]).build())
},
Ok,
)
}

fn get_modules(modules: &[Module]) -> Vec<Module> {
modules
.iter()
.flat_map(|module| {
if let Some(file_name) = &module.from_file {
match get_module_from_file(file_name) {
Err(e) => {
error!("Failed to get module from {file_name}: {e}");
vec![]
}
Ok(module_ext) => get_modules(&module_ext.modules),
}
} else {
vec![module.clone()]
}
})
.collect()
}

fn print_full_recipe(recipe: &Recipe) -> String {
let module_list: Vec<Module> = get_modules(&recipe.modules_ext.modules);

let recipe = Recipe::builder()
.name(recipe.name.as_ref())
.description(recipe.description.as_ref())
.base_image(recipe.base_image.as_ref())
.image_version(recipe.image_version.as_ref())
.extra(recipe.extra.clone())
.modules_ext(ModuleExt::builder().modules(module_list).build())
.build();

serde_yaml::to_string(&recipe).unwrap_or_else(|e| {
error!("Failed to serialize recipe: {e}");
format!("Error rendering recipe!!\n{e}")
})
}
// ============================================================================= //

#[cfg(test)]
Expand Down
9 changes: 2 additions & 7 deletions src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use std::{

use anyhow::{anyhow, bail, Result};
use clap::Args;
use format_serde_error::SerdeError;
use log::{debug, info, trace, warn};
use typed_builder::TypedBuilder;

Expand Down Expand Up @@ -196,9 +195,7 @@ impl BuildCommand {
bail!("Failed to get credentials");
}

let recipe_str = fs::read_to_string(recipe_path)?;
let recipe: Recipe = serde_yaml::from_str(&recipe_str)
.map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?;
let recipe = Recipe::parse(&recipe_path)?;
trace!("recipe: {recipe:#?}");

// Get values for image
Expand Down Expand Up @@ -282,9 +279,7 @@ impl BuildCommand {
fn build_image(&self, recipe_path: &Path) -> Result<()> {
trace!("BuildCommand::build_image()");

let recipe_str = fs::read_to_string(recipe_path)?;
let recipe: Recipe = serde_yaml::from_str(&recipe_str)
.map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?;
let recipe = Recipe::parse(&recipe_path)?;

let tags = recipe.generate_tags();

Expand Down
9 changes: 2 additions & 7 deletions src/commands/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::{

use anyhow::{bail, Result};
use clap::Args;
use format_serde_error::SerdeError;
use log::{debug, info, trace};
use typed_builder::TypedBuilder;
use users::{Users, UsersCache};
Expand Down Expand Up @@ -44,9 +43,7 @@ impl BlueBuildCommand for UpgradeCommand {

check_can_run()?;

let recipe_str = fs::read_to_string(&self.common.recipe)?;
let recipe: Recipe = serde_yaml::from_str(&recipe_str)
.map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?;
let recipe = Recipe::parse(&self.common.recipe)?;

let mut build = BuildCommand::builder()
.recipe(self.common.recipe.clone())
Expand Down Expand Up @@ -93,9 +90,7 @@ impl BlueBuildCommand for RebaseCommand {

check_can_run()?;

let recipe_str = fs::read_to_string(&self.common.recipe)?;
let recipe: Recipe = serde_yaml::from_str(&recipe_str)
.map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?;
let recipe = Recipe::parse(&self.common.recipe)?;

let mut build = BuildCommand::builder()
.recipe(self.common.recipe.clone())
Expand Down
57 changes: 1 addition & 56 deletions src/commands/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ use std::{
use anyhow::Result;
use askama::Template;
use clap::Args;
use format_serde_error::SerdeError;
use log::{debug, error, info, trace};
use typed_builder::TypedBuilder;

use crate::{
constants::{self},
module_recipe::{Module, ModuleExt, Recipe},
module_recipe::{Module, Recipe},
};

use super::BlueBuildCommand;
Expand All @@ -24,18 +23,10 @@ pub struct ContainerFileTemplate<'a> {
recipe: &'a Recipe<'a>,
recipe_path: &'a Path,

module_template: ModuleTemplate<'a>,

#[builder(default)]
export_script: ExportsTemplate,
}

#[derive(Debug, Clone, Template, TypedBuilder)]
#[template(path = "Containerfile.module", escape = "none")]
pub struct ModuleTemplate<'a> {
module_ext: &'a ModuleExt,
}

#[derive(Debug, Clone, Default, Template)]
#[template(path = "export.sh", escape = "none")]
pub struct ExportsTemplate;
Expand Down Expand Up @@ -83,11 +74,6 @@ impl TemplateCommand {
let template = ContainerFileTemplate::builder()
.recipe(&recipe_de)
.recipe_path(&recipe_path)
.module_template(
ModuleTemplate::builder()
.module_ext(&recipe_de.modules_ext)
.build(),
)
.build();

let output_str = template.render()?;
Expand Down Expand Up @@ -168,47 +154,6 @@ fn print_containerfile(containerfile: &str) -> String {
file
}

#[must_use]
fn template_module_from_file(file_name: &str) -> String {
debug!("get_module_from_file({file_name})");

let file_path = PathBuf::from("config").join(file_name);
let file = fs::read_to_string(file_path).unwrap_or_else(|e| {
error!("Failed to read module {file_name}: {e}");
process::exit(1);
});

let template_err_fn = |e| {
error!("Failed to render module {file_name}: {e}");
process::exit(1);
};

serde_yaml::from_str::<ModuleExt>(file.as_str()).map_or_else(
|_| {
let module = serde_yaml::from_str::<Module>(file.as_str()).unwrap_or_else(|err| {
error!(
"Failed to deserialize module {file_name}: {}",
SerdeError::new(file_name.to_owned(), err)
);
process::exit(1);
});

ModuleTemplate::builder()
.module_ext(&ModuleExt::builder().modules(vec![module]).build())
.build()
.render()
.unwrap_or_else(template_err_fn)
},
|module_ext| {
ModuleTemplate::builder()
.module_ext(&module_ext)
.build()
.render()
.unwrap_or_else(template_err_fn)
},
)
}

fn print_module_context(module: &Module) -> String {
serde_json::to_string(module).unwrap_or_else(|e| {
error!("Failed to parse module: {e}");
Expand Down
66 changes: 63 additions & 3 deletions src/module_recipe.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
use std::{borrow::Cow, collections::HashMap, env, fs, path::Path, process::Command};
use std::{
borrow::Cow,
collections::HashMap,
env, fs,
path::{Path, PathBuf},
process::Command,
};

use anyhow::Result;
use chrono::Local;
use format_serde_error::SerdeError;
use indexmap::IndexMap;
use log::{debug, info, trace, warn};
use log::{debug, error, info, trace, warn};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use serde_yaml::Value;
Expand Down Expand Up @@ -136,7 +142,12 @@ impl<'a> Recipe<'a> {

debug!("Recipe contents: {file}");

Ok(serde_yaml::from_str::<Recipe>(&file).map_err(|err| SerdeError::new(file, err))?)
let mut recipe =
serde_yaml::from_str::<Recipe>(&file).map_err(|err| SerdeError::new(file, err))?;

recipe.modules_ext.modules = Module::get_modules(&recipe.modules_ext.modules);

Ok(recipe)
}

fn get_os_version(&self) -> String {
Expand Down Expand Up @@ -197,6 +208,34 @@ pub struct ModuleExt {
pub modules: Vec<Module>,
}

impl ModuleExt {
pub fn parse_module_from_file(file_name: &str) -> Result<ModuleExt> {
let file_path = PathBuf::from("config").join(file_name);
let file_path = if file_path.is_absolute() {
file_path
} else {
std::env::current_dir()?.join(file_path)
};

let file = fs::read_to_string(file_path.clone())?;

serde_yaml::from_str::<ModuleExt>(&file).map_or_else(
|err| -> Result<ModuleExt> {
error!(
"Failed to parse module from {}: {}",
file_path.display(),
SerdeError::new(file.to_owned(), err).to_string()
);

let module = serde_yaml::from_str::<Module>(&file)
.map_err(|err| SerdeError::new(file, err))?;
Ok(ModuleExt::builder().modules(vec![module]).build())
},
Ok,
)
}
}

#[derive(Serialize, Deserialize, Debug, Clone, TypedBuilder)]
pub struct Module {
#[builder(default, setter(into, strip_option))]
Expand All @@ -212,6 +251,27 @@ pub struct Module {
pub config: IndexMap<String, Value>,
}

impl Module {
pub fn get_modules(modules: &[Self]) -> Vec<Self> {
modules
.iter()
.flat_map(|module| {
if let Some(file_name) = &module.from_file {
match ModuleExt::parse_module_from_file(file_name) {
Err(e) => {
error!("Failed to get module from {file_name}: {e}");
vec![]
}
Ok(module_ext) => Self::get_modules(&module_ext.modules),
}
} else {
vec![module.clone()]
}
})
.collect()
}
}

#[derive(Deserialize, Debug, Clone)]
struct ImageInspection {
#[serde(alias = "Labels")]
Expand Down
21 changes: 20 additions & 1 deletion templates/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ ARG CONFIG_DIRECTORY="/tmp/config"
ARG IMAGE_NAME="{{ recipe.name }}"
ARG BASE_IMAGE="{{ recipe.base_image }}"

{{ module_template }}
{%- for module in recipe.modules_ext.modules %}
{%- if let Some(type) = module.module_type %}
{%- if type == "containerfile" %}
{%- if let Some(containerfiles) = self::get_containerfile_list(module) %}
{%- for c in containerfiles %}
{{ self::print_containerfile(c) }}
{%- endfor %}
{%- endif %}
{%- else if type == "files" %}
{%- if let Some(files) = self::get_files_list(module) %}
{%- for (src, dest) in files %}
COPY {{ src }} {{ dest }}
{%- endfor %}
{%- endif %}
{%- else %}
RUN chmod +x /tmp/modules/{{ type }}/{{ type }}.sh && source /tmp/exports.sh && /tmp/modules/{{ type }}/{{ type }}.sh '{{ self::print_module_context(module) }}'
{%- endif %}
{%- endif %}
{%- endfor %}


RUN rm -rf /tmp/* /var/* && ostree container commit
22 changes: 0 additions & 22 deletions templates/Containerfile.module

This file was deleted.

0 comments on commit 245ddf0

Please sign in to comment.