Skip to content

Commit

Permalink
Merge pull request #300 from Metaswitch/md/uniteerrors
Browse files Browse the repository at this point in the history
Combine errors into a single FlokiError enum.
  • Loading branch information
maxdymond authored Jul 7, 2023
2 parents 6dfe95c + 6e5b91b commit 3cc2884
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Status: Available for use
can use `toml(file="<filepath>")` in order to load values.
- Add `floki render` to print out the rendered configuration template.
- Switch rust image to `rust:1-alpine3.18` as it's better maintained.
- Combine errors into a single FlokiError enum.

### Fixed

Expand Down
33 changes: 17 additions & 16 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/// Configuration file format for floki
use crate::errors;
use crate::errors::FlokiError;
use crate::image;
use anyhow::Error;
use serde::{Deserialize, Serialize};
use tera::from_value;
use tera::Context;
Expand Down Expand Up @@ -126,7 +125,7 @@ fn tomlloader(args: &HashMap<String, tera::Value>) -> tera::Result<tera::Value>
}

// Renders a template from a given string.
pub fn render_template(template: &str, source_filename: &Path) -> Result<String, Error> {
pub fn render_template(template: &str, source_filename: &Path) -> Result<String, FlokiError> {
let template_path = source_filename.display().to_string();

debug!("Rendering template: {template_path}");
Expand All @@ -140,7 +139,7 @@ pub fn render_template(template: &str, source_filename: &Path) -> Result<String,
tera.register_function("toml", tomlloader);

tera.add_raw_template(&template_path, template)
.map_err(|e| errors::FlokiError::ProblemRenderingTemplate {
.map_err(|e| FlokiError::ProblemRenderingTemplate {
name: template_path.clone(),
error: e,
})?;
Expand All @@ -152,35 +151,37 @@ pub fn render_template(template: &str, source_filename: &Path) -> Result<String,
context.insert("env", &vars);

// Render the floki file to string using the context.
Ok(tera.render(&template_path, &context)?)
tera.render(&template_path, &context)
.map_err(|e| FlokiError::ProblemRenderingTemplate {
name: template_path.clone(),
error: e,
})
}

impl FlokiConfig {
pub fn render(file: &Path) -> Result<String, Error> {
let content = std::fs::read_to_string(file).map_err(|e| {
errors::FlokiError::ProblemOpeningConfigYaml {
pub fn render(file: &Path) -> Result<String, FlokiError> {
let content =
std::fs::read_to_string(file).map_err(|e| FlokiError::ProblemOpeningConfigYaml {
name: file.display().to_string(),
error: e,
}
})?;
})?;

// Render the template first before parsing it.
render_template(&content, file)
}

pub fn from_file(file: &Path) -> Result<Self, Error> {
pub fn from_file(file: &Path) -> Result<Self, FlokiError> {
debug!("Reading configuration file: {:?}", file);

// Render the output from the configuration file before parsing.
let output = Self::render(file)?;

// Parse the rendered floki file from the string.
let mut config: FlokiConfig = serde_yaml::from_str(&output).map_err(|e| {
errors::FlokiError::ProblemParsingConfigYaml {
let mut config: FlokiConfig =
serde_yaml::from_str(&output).map_err(|e| FlokiError::ProblemParsingConfigYaml {
name: file.display().to_string(),
error: e,
}
})?;
})?;

// Ensure the path to an external yaml file is correct.
// If the image.yaml.path file is relative, then it should
Expand All @@ -191,7 +192,7 @@ impl FlokiConfig {
if yaml.file.is_relative() {
yaml.file = file
.parent()
.ok_or_else(|| errors::FlokiInternalError::InternalAssertionFailed {
.ok_or_else(|| FlokiError::InternalAssertionFailed {
description: format!(
"could not construct path to external yaml file '{:?}'",
&yaml.file
Expand Down
14 changes: 6 additions & 8 deletions src/environment.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// Query the current user environment
use crate::errors;
use crate::errors::FlokiError;
use anyhow::Error;
use std::env;
use std::ffi::OsString;
Expand Down Expand Up @@ -79,14 +79,14 @@ fn find_floki_yaml(current_directory: &path::Path) -> Result<path::PathBuf, Erro
.ancestors()
.map(|a| a.join("floki.yaml"))
.find(|f| f.is_file())
.ok_or_else(|| errors::FlokiError::ProblemFindingConfigYaml {}.into())
.ok_or_else(|| FlokiError::ProblemFindingConfigYaml {}.into())
}

/// Take a file path, and return a tuple consisting of its parent directory and the file path
fn locate_file_in_parents(path: path::PathBuf) -> Result<(path::PathBuf, path::PathBuf), Error> {
let dir = path
.parent()
.ok_or_else(|| errors::FlokiInternalError::InternalAssertionFailed {
.ok_or_else(|| FlokiError::InternalAssertionFailed {
description: format!("config_file '{:?}' does not have a parent", &path),
})?
.to_path_buf();
Expand Down Expand Up @@ -116,11 +116,9 @@ fn get_floki_work_path(uid: nix::unistd::Uid) -> path::PathBuf {
/// Normalize the filepath - this turns a relative path into an absolute one - to
/// do this it must locate the file in the filesystem, and hence it may fail.
fn normalize_path(path: path::PathBuf) -> Result<path::PathBuf, Error> {
let res = std::fs::canonicalize(&path).map_err(|e| {
errors::FlokiError::ProblemNormalizingFilePath {
name: path.display().to_string(),
error: e,
}
let res = std::fs::canonicalize(&path).map_err(|e| FlokiError::ProblemNormalizingFilePath {
name: path.display().to_string(),
error: e,
})?;

Ok(res)
Expand Down
23 changes: 8 additions & 15 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ pub enum FlokiError {

#[error("Malformed item in docker_switches: {item}")]
MalformedDockerSwitch { item: String },

/// Internal error for floki - these represent failed assumptions of
/// the developers, and shouldn't actually manifest.
#[error("An internal assertion failed '{description}'. This is probably a bug!")]
InternalAssertionFailed { description: String },

#[error("Invalid verbosity setting of {setting:?}. Use a setting between 0 and 3 (-vvv)")]
InvalidVerbositySetting { setting: u8 },
}

/// Generate a summary string for a process exiting
Expand Down Expand Up @@ -98,18 +106,3 @@ impl fmt::Display for FlokiSubprocessExitStatus {
)
}
}

/// Internal error types for floki - these represent failed assumptions of
/// the developers, and shouldn't actually manifest.
#[derive(Debug, thiserror::Error)]
pub enum FlokiInternalError {
#[error("An internal assertion failed '{description}'. This is probably a bug!")]
InternalAssertionFailed { description: String },
}

/// Errors made by floki users.
#[derive(Debug, thiserror::Error)]
pub enum FlokiUserError {
#[error("Invalid verbosity setting of {setting:?}. Use a setting between 0 and 3 (-vvv)")]
InvalidVerbositySetting { setting: u8 },
}
7 changes: 2 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use anyhow::Error;
use cli::{Cli, Subcommand};
use config::FlokiConfig;
use environment::Environment;
use errors::FlokiError;
use structopt::StructOpt;

fn main() -> Result<(), Error> {
Expand Down Expand Up @@ -87,11 +88,7 @@ fn configure_logging(verbosity: u8) -> Result<(), Error> {
1 => log::LevelFilter::Info,
2 => log::LevelFilter::Debug,
3 => log::LevelFilter::Trace,
_ => {
return Err(
errors::FlokiUserError::InvalidVerbositySetting { setting: verbosity }.into(),
)
}
_ => return Err(FlokiError::InvalidVerbositySetting { setting: verbosity }.into()),
};
simplelog::TermLogger::init(
level,
Expand Down

0 comments on commit 3cc2884

Please sign in to comment.