refactor: Swtich to using bon for builder pattern

This commit is contained in:
Gerald Pinder 2024-09-21 13:15:45 -04:00
parent aed7e275f2
commit 0c52cf6a54
36 changed files with 326 additions and 314 deletions

View file

@ -22,7 +22,10 @@ use serde::Deserialize;
use tempdir::TempDir;
use crate::{
drivers::image_metadata::ImageMetadata,
drivers::{
image_metadata::ImageMetadata,
opts::{RunOptsEnv, RunOptsVolume},
},
logging::{CommandLogging, Logger},
signal_handler::{add_cid, remove_cid, ContainerId, ContainerRuntime},
};
@ -321,7 +324,7 @@ impl InspectDriver for DockerDriver {
let output = Self::run_output(
&RunOpts::builder()
.image(SKOPEO_IMAGE)
.args(string_vec!["inspect", url.clone()])
.args(bon::vec!["inspect", &url])
.remove(true)
.build(),
)
@ -379,13 +382,13 @@ fn docker_run(opts: &RunOpts, cid_file: &Path) -> Command {
if opts.privileged => "--privileged",
if opts.remove => "--rm",
if opts.pull => "--pull=always",
for volume in opts.volumes => [
for RunOptsVolume { path_or_vol_name, container_path } in opts.volumes.iter() => [
"--volume",
format!("{}:{}", volume.path_or_vol_name, volume.container_path),
format!("{path_or_vol_name}:{container_path}"),
],
for env in opts.env_vars => [
for RunOptsEnv { key, value } in opts.env_vars.iter() => [
"--env",
format!("{}={}", env.key, env.value),
format!("{key}={value}"),
],
|command| {
match (opts.uid, opts.gid) {
@ -395,7 +398,7 @@ fn docker_run(opts: &RunOpts, cid_file: &Path) -> Command {
}
},
&*opts.image,
for opts.args,
for arg in opts.args.iter() => &**arg,
);
trace!("{command:?}");

View file

@ -137,7 +137,7 @@ mod test {
constants::{
GITHUB_EVENT_NAME, GITHUB_EVENT_PATH, GITHUB_REF_NAME, GITHUB_SHA, PR_EVENT_NUMBER,
},
cowstr_vec, string_vec,
string_vec,
test_utils::set_env_var,
};
use oci_distribution::Reference;
@ -230,7 +230,7 @@ mod test {
)]
#[case::default_branch_alt_tags(
setup_default_branch,
Some(cowstr_vec![TEST_TAG_1, TEST_TAG_2]),
Some(bon::vec![TEST_TAG_1, TEST_TAG_2]),
string_vec![
TEST_TAG_1,
format!("{TEST_TAG_1}-40"),
@ -249,7 +249,7 @@ mod test {
)]
#[case::pr_branch_alt_tags(
setup_pr_branch,
Some(cowstr_vec![TEST_TAG_1, TEST_TAG_2]),
Some(bon::vec![TEST_TAG_1, TEST_TAG_2]),
string_vec![
format!("pr-12-{TEST_TAG_1}-40"),
format!("{COMMIT_SHA}-{TEST_TAG_1}-40"),
@ -264,7 +264,7 @@ mod test {
)]
#[case::branch_alt_tags(
setup_branch,
Some(cowstr_vec![TEST_TAG_1, TEST_TAG_2]),
Some(bon::vec![TEST_TAG_1, TEST_TAG_2]),
string_vec![
format!("br-{BR_REF_NAME}-{TEST_TAG_1}-40"),
format!("{COMMIT_SHA}-{TEST_TAG_1}-40"),
@ -284,7 +284,7 @@ mod test {
let mut tags = GithubDriver::generate_tags(
&GenerateTagsOpts::builder()
.oci_ref(&oci_ref)
.alt_tags(alt_tags)
.maybe_alt_tags(alt_tags)
.build(),
)
.unwrap();

View file

@ -149,7 +149,7 @@ mod test {
CI_PIPELINE_SOURCE, CI_PROJECT_NAME, CI_PROJECT_NAMESPACE, CI_REGISTRY, CI_SERVER_HOST,
CI_SERVER_PROTOCOL,
},
cowstr_vec, string_vec,
string_vec,
test_utils::set_env_var,
};
use oci_distribution::Reference;
@ -238,7 +238,7 @@ mod test {
)]
#[case::default_branch_alt_tags(
setup_default_branch,
Some(cowstr_vec![TEST_TAG_1, TEST_TAG_2]),
Some(bon::vec![TEST_TAG_1, TEST_TAG_2]),
string_vec![
TEST_TAG_1,
format!("{TEST_TAG_1}-40"),
@ -257,7 +257,7 @@ mod test {
)]
#[case::pr_branch_alt_tags(
setup_mr_branch,
Some(cowstr_vec![TEST_TAG_1, TEST_TAG_2]),
Some(bon::vec![TEST_TAG_1, TEST_TAG_2]),
string_vec![
format!("mr-12-{TEST_TAG_1}-40"),
format!("{COMMIT_SHA}-{TEST_TAG_1}-40"),
@ -272,7 +272,7 @@ mod test {
)]
#[case::branch_alt_tags(
setup_branch,
Some(cowstr_vec![TEST_TAG_1, TEST_TAG_2]),
Some(bon::vec![TEST_TAG_1, TEST_TAG_2]),
string_vec![
format!("br-{BR_REF_NAME}-{TEST_TAG_1}-40"),
format!("{COMMIT_SHA}-{TEST_TAG_1}-40"),
@ -292,7 +292,7 @@ mod test {
let mut tags = GitlabDriver::generate_tags(
&GenerateTagsOpts::builder()
.oci_ref(&oci_ref)
.alt_tags(alt_tags)
.maybe_alt_tags(alt_tags)
.build(),
)
.unwrap();

View file

@ -1,65 +1,63 @@
use std::{borrow::Cow, path::Path};
use typed_builder::TypedBuilder;
use bon::Builder;
use super::CompressionType;
/// Options for building
#[derive(Debug, Clone, TypedBuilder)]
pub struct BuildOpts<'a> {
#[builder(setter(into))]
pub image: Cow<'a, str>,
#[derive(Debug, Clone, Builder)]
pub struct BuildOpts<'scope> {
#[builder(into)]
pub image: Cow<'scope, str>,
#[builder(default)]
pub squash: bool,
#[builder(setter(into))]
pub containerfile: Cow<'a, Path>,
#[builder(into)]
pub containerfile: Cow<'scope, Path>,
}
#[derive(Debug, Clone, TypedBuilder)]
pub struct TagOpts<'a> {
#[builder(setter(into))]
pub src_image: Cow<'a, str>,
#[derive(Debug, Clone, Builder)]
pub struct TagOpts<'scope> {
#[builder(into)]
pub src_image: Cow<'scope, str>,
#[builder(setter(into))]
pub dest_image: Cow<'a, str>,
#[builder(into)]
pub dest_image: Cow<'scope, str>,
}
#[derive(Debug, Clone, TypedBuilder)]
pub struct PushOpts<'a> {
#[builder(setter(into))]
pub image: Cow<'a, str>,
#[builder(default, setter(strip_option))]
#[derive(Debug, Clone, Builder)]
pub struct PushOpts<'scope> {
#[builder(into)]
pub image: Cow<'scope, str>,
pub compression_type: Option<CompressionType>,
}
/// Options for building, tagging, and pusing images.
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone, TypedBuilder)]
pub struct BuildTagPushOpts<'a> {
#[derive(Debug, Clone, Builder)]
pub struct BuildTagPushOpts<'scope> {
/// The base image name.
///
/// NOTE: This SHOULD NOT contain the tag of the image.
///
/// NOTE: You cannot have this set with `archive_path` set.
#[builder(default, setter(into, strip_option))]
pub image: Option<Cow<'a, str>>,
#[builder(into)]
pub image: Option<Cow<'scope, str>>,
/// The path to the archive file.
///
/// NOTE: You cannot have this set with image set.
#[builder(default, setter(into, strip_option))]
pub archive_path: Option<Cow<'a, str>>,
#[builder(into)]
pub archive_path: Option<Cow<'scope, str>>,
/// The path to the Containerfile to build.
#[builder(setter(into))]
pub containerfile: Cow<'a, Path>,
#[builder(into)]
pub containerfile: Cow<'scope, Path>,
/// The list of tags for the image being built.
#[builder(default, setter(into))]
pub tags: Cow<'a, [String]>,
#[builder(default, into)]
pub tags: Vec<Cow<'scope, str>>,
/// Enable pushing the image.
#[builder(default)]

View file

@ -1,24 +1,24 @@
use std::borrow::Cow;
use bon::Builder;
use oci_distribution::Reference;
use typed_builder::TypedBuilder;
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct GenerateTagsOpts<'scope> {
pub oci_ref: &'scope Reference,
#[builder(default, setter(into))]
#[builder(into)]
pub alt_tags: Option<Vec<Cow<'scope, str>>>,
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct GenerateImageNameOpts<'scope> {
#[builder(default, setter(into))]
#[builder(into)]
pub name: Cow<'scope, str>,
#[builder(default, setter(into))]
#[builder(into)]
pub registry: Option<Cow<'scope, str>>,
#[builder(default, setter(into))]
#[builder(into)]
pub registry_namespace: Option<Cow<'scope, str>>,
}

View file

@ -1,12 +1,12 @@
use std::borrow::Cow;
use typed_builder::TypedBuilder;
use bon::Builder;
#[derive(Debug, Clone, TypedBuilder)]
pub struct GetMetadataOpts<'a> {
#[builder(setter(into))]
pub image: Cow<'a, str>,
#[derive(Debug, Clone, Builder)]
pub struct GetMetadataOpts<'scope> {
#[builder(into)]
pub image: Cow<'scope, str>,
#[builder(default, setter(into, strip_option))]
pub tag: Option<Cow<'a, str>>,
#[builder(into)]
pub tag: Option<Cow<'scope, str>>,
}

View file

@ -1,30 +1,23 @@
use std::borrow::Cow;
use typed_builder::TypedBuilder;
use bon::Builder;
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct RunOpts<'scope> {
#[builder(setter(into))]
#[builder(into)]
pub image: Cow<'scope, str>,
#[builder(default, setter(into))]
pub args: Cow<'scope, [String]>,
#[builder(default, into)]
pub args: Vec<Cow<'scope, str>>,
#[builder(default, setter(into))]
#[builder(default, into)]
pub env_vars: Vec<RunOptsEnv<'scope>>,
#[builder(default, setter(into))]
#[builder(default, into)]
pub volumes: Vec<RunOptsVolume<'scope>>,
#[builder(default, setter(strip_option))]
pub uid: Option<u32>,
#[builder(default, setter(strip_option))]
pub gid: Option<u32>,
#[builder(default, setter(into))]
pub workdir: Cow<'scope, str>,
#[builder(default)]
pub privileged: bool,
@ -35,12 +28,12 @@ pub struct RunOpts<'scope> {
pub remove: bool,
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct RunOptsVolume<'scope> {
#[builder(setter(into))]
#[builder(into)]
pub path_or_vol_name: Cow<'scope, str>,
#[builder(setter(into))]
#[builder(into)]
pub container_path: Cow<'scope, str>,
}
@ -48,7 +41,7 @@ pub struct RunOptsVolume<'scope> {
macro_rules! run_volumes {
($($host:expr => $container:expr),+ $(,)?) => {
{
vec![
::bon::vec![
$($crate::drivers::opts::RunOptsVolume::builder()
.path_or_vol_name($host)
.container_path($container)
@ -58,12 +51,12 @@ macro_rules! run_volumes {
};
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct RunOptsEnv<'scope> {
#[builder(setter(into))]
#[builder(into)]
pub key: Cow<'scope, str>,
#[builder(setter(into))]
#[builder(into)]
pub value: Cow<'scope, str>,
}
@ -71,7 +64,7 @@ pub struct RunOptsEnv<'scope> {
macro_rules! run_envs {
($($key:expr => $value:expr),+ $(,)?) => {
{
vec![
::bon::vec![
$($crate::drivers::opts::RunOptsEnv::builder()
.key($key)
.value($value)

View file

@ -4,8 +4,8 @@ use std::{
path::{Path, PathBuf},
};
use bon::Builder;
use miette::{IntoDiagnostic, Result};
use typed_builder::TypedBuilder;
use zeroize::{Zeroize, Zeroizing};
pub enum PrivateKey {
@ -13,6 +13,18 @@ pub enum PrivateKey {
Path(PathBuf),
}
impl std::fmt::Display for PrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(
match *self {
Self::Env(ref env) => format!("env://{env}"),
Self::Path(ref path) => format!("{}", path.display()),
}
.as_str(),
)
}
}
pub trait PrivateKeyContents<T>
where
T: Zeroize,
@ -40,39 +52,27 @@ impl PrivateKeyContents<String> for PrivateKey {
}
}
impl std::fmt::Display for PrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(
match *self {
Self::Env(ref env) => format!("env://{env}"),
Self::Path(ref path) => format!("{}", path.display()),
}
.as_str(),
)
}
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct GenerateKeyPairOpts<'scope> {
#[builder(setter(into, strip_option))]
#[builder(into)]
pub dir: Option<Cow<'scope, Path>>,
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct CheckKeyPairOpts<'scope> {
#[builder(setter(into, strip_option))]
#[builder(into)]
pub dir: Option<Cow<'scope, Path>>,
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct SignOpts<'scope> {
#[builder(setter(into))]
#[builder(into)]
pub image: Cow<'scope, str>,
#[builder(default, setter(into, strip_option))]
#[builder(into)]
pub key: Option<Cow<'scope, str>>,
#[builder(default, setter(into, strip_option))]
#[builder(into)]
pub dir: Option<Cow<'scope, Path>>,
}
@ -85,22 +85,22 @@ pub enum VerifyType<'scope> {
},
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct VerifyOpts<'scope> {
#[builder(setter(into))]
#[builder(into)]
pub image: Cow<'scope, str>,
pub verify_type: VerifyType<'scope>,
}
#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, Builder)]
pub struct SignVerifyOpts<'scope> {
#[builder(setter(into))]
#[builder(into)]
pub image: Cow<'scope, str>,
#[builder(default, setter(into, strip_option))]
#[builder(into)]
pub tag: Option<Cow<'scope, str>>,
#[builder(default, setter(into, strip_option))]
#[builder(into)]
pub dir: Option<Cow<'scope, Path>>,
/// Enable retry logic for pushing.

View file

@ -5,7 +5,7 @@ use std::{
time::Duration,
};
use blue_build_utils::{cmd, constants::SKOPEO_IMAGE, credentials::Credentials, string_vec};
use blue_build_utils::{cmd, constants::SKOPEO_IMAGE, credentials::Credentials};
use colored::Colorize;
use indicatif::{ProgressBar, ProgressStyle};
use log::{debug, error, info, trace, warn};
@ -15,7 +15,10 @@ use serde::Deserialize;
use tempdir::TempDir;
use crate::{
drivers::image_metadata::ImageMetadata,
drivers::{
image_metadata::ImageMetadata,
opts::{RunOptsEnv, RunOptsVolume},
},
logging::{CommandLogging, Logger},
signal_handler::{add_cid, remove_cid, ContainerId, ContainerRuntime},
};
@ -198,7 +201,7 @@ impl InspectDriver for PodmanDriver {
let output = Self::run_output(
&RunOpts::builder()
.image(SKOPEO_IMAGE)
.args(string_vec!["inspect", url.clone()])
.args(bon::vec!["inspect", &url])
.remove(true)
.build(),
)
@ -277,16 +280,16 @@ fn podman_run(opts: &RunOpts, cid_file: &Path) -> Command {
],
if opts.remove => "--rm",
if opts.pull => "--pull=always",
for volume in opts.volumes => [
for RunOptsVolume { path_or_vol_name, container_path } in opts.volumes.iter() => [
"--volume",
format!("{}:{}", volume.path_or_vol_name, volume.container_path),
format!("{path_or_vol_name}:{container_path}"),
],
for env in opts.env_vars => [
for RunOptsEnv { key, value } in opts.env_vars.iter() => [
"--env",
format!("{}={}", env.key, env.value),
format!("{key}={value}"),
],
&*opts.image,
for opts.args,
for arg in opts.args.iter() => &**arg,
);
trace!("{command:?}");

View file

@ -105,7 +105,7 @@ pub trait BuildDriver {
let mut image_list = Vec::with_capacity(opts.tags.len());
for tag in opts.tags.as_ref() {
for tag in &opts.tags {
debug!("Tagging {} with {tag}", &full_image);
let tagged_image = format!("{image}:{tag}");